Skip to content

Chez+racket: support building with cosmopolitan libc #5004

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

jjsullivan5196
Copy link
Contributor

@jjsullivan5196 jjsullivan5196 commented May 29, 2024

Checklist
  • Feature
  • documentation

Description of change

This patch adds some minimal scaffolding to allow building and running Chez and the Racket main distribution with cosmopolitan libc, affording access to 6 operating systems with a single binary https://github.com/jart/cosmopolitan

The main contents of this patch are a couple of platform checks, and an addition to Racket's bootup procedure such that it can load the start image and packages from an embedded ZIP object store provided by the platform. I know this isn't exactly new in terms of what raco exe can do, but it does collapse the amount of binary images needed to ship to different platforms, while taking away ABI variability/build churn.

The shell script included in the commit message demonstrates shipping the main distribution as a single binary file, which runs on amd64 Linux, Windows 10, MacOS, NetBSD, OpenBSD, and FreeBSD. These are all covered by the static minimal racket binary built with the cosmopolitan toolchain. aarch64 should also work, though I still need to try it out.

Of course, this isn't all sunshine and rainbows. Cosmo does ship its own implementation of a POSIX ABI to cover most OS interfacing, but Racket assumes a lot about the underlying system from build time (such as it pertains to the foreign interface for instance, getting the gui package to work might be a challenge). I don't want to make outlandish claims of what's possible or worth doing, but I thought this was interesting and useful enough to share with the maintainers. Also where I might not be expert in the details of the platform, @jart or @ahgamut should be able to provide some clarification. I'd be happy to make any changes the authors would prefer of course. I'll also add an accompanying PR to the Chez repo cisco/ChezScheme#837

Tested on linux-amd64 with cosmocc 3.3.10. This patch allows cosmocc
to build the main racket distribution as an Actually Portable
Executable

https://github.com/jart/cosmopolitan?tab=readme-ov-file#cosmopolitan
https://cosmo.zip/pub/cosmocc/

With cosmocc unzipped in `/opt/cosmocc` and a `/zip` directory with
user read+write, run this script in the repo root to build
`racket.com`:

```sh
REPO_ROOT=$PWD
COSMOCC=/opt/cosmocc
MAKE=$COSMOCC/bin/make
export CC=$COSMOCC/bin/x86_64-unknown-cosmo-cc
export AR=$COSMOCC/bin/x86_64-unknown-cosmo-ar
export STRIP=echo
export COSMOPOLITAN_DISABLE_ZIPOS=1

$MAKE pb-fetch

mkdir racket/src/build || true
cd racket/src/build
../configure --prefix=/zip/usr

rm -rf /zip/usr || true
rm -rf ./dist || true

$MAKE -j
$MAKE install

cp -r /zip ./dist
cd ./dist
mv ./usr/bin/racket ./

$COSMOCC/bin/fixupobj ./racket
$COSMOCC/bin/apelink -o ./racket.zip ./racket

zip -r ./racket.zip usr/

cd $REPO_ROOT
mv racket/src/build/dist/racket.zip ./racket.com
```
@samth
Copy link
Member

samth commented May 29, 2024

I'm confused about why this particular situation for locating .boot files should be hardcoded. Can using --enable-scheme in configure handle this case? If not, why not -- maybe it should be extended.

Also, significant parts of base Racket depend on the ffi; for example the ability to use openssl to download packages over HTTPS or use sqlite to manage databases when building code and documentation. Do those work with this set of changes?

@jjsullivan5196
Copy link
Contributor Author

jjsullivan5196 commented May 29, 2024

@samth

Also, significant parts of base Racket depend on the ffi; for example the ability to use openssl to download packages over HTTPS or use sqlite to manage databases when building code and documentation. Do those work with this set of changes?

On linux it does (raco can retrieve packages without modification), but I can't say the same for other OSes as it looks like (system-type) only uses information available at build time. (ie the main distribution built on linux will still eval (system-type 'os*) to 'linux on windows)

I don't know if that would be trivial to change, I did see the source in system.ss and it didn't look too bad, but I'm not familiar with how the build steps capture that information.

Also note this doesn't touch the behavior of other libc implementations. I am able to get a REPL on Windows 10 and Linux with the built distribution in racket.com at least.

I'm confused about why this particular situation for locating .boot files should be hardcoded. Can using --enable-scheme in configure handle this case? If not, why not -- maybe it should be extended.

I agree that its not particularly ideal, but since the APE image always provides the embedded zip archive, it seems like the most reliable solution for storing the boot images. I could try to work it into the build steps somehow, but I didn't want to disrupt how the existing targets work.

Also

john@crunchbox:~/src/racket/racket/src/build$ ../configure --help-cs | grep scheme
  --enable-scheme=<path>  use <path> as Chez Scheme for build

Maybe you were referring to a different configure option? As far as I understand, there's no need to use different Chez sources for this to work.

It probably would be helpful to at least sketch working some of this into CI/build steps. I'll try what I can, but do let me know if there's anything in particular that would be helpful to look at.

@jjsullivan5196 jjsullivan5196 marked this pull request as draft May 29, 2024 20:22
@samth
Copy link
Member

samth commented May 29, 2024

If you want to build a cross build, you can see the --build, --host, and --target configure options. But I guess this points to a bigger issue -- what should this even do when run on a machine different from how it was compiled? Building against cosmopolitan libc doesn't sound very useful if the result can only run on one platform, but it seems like changing that would require much bigger changes than proposed here.

--enable-scheme should point to how to find the scheme.boot and petite.boot files. racket.boot is an intermediate build product that gets combined with the other boot files into the racket executable. So I'm confused about why they would be in a global store.

@jjsullivan5196
Copy link
Contributor Author

jjsullivan5196 commented May 29, 2024

but it seems like changing that would require much bigger changes than proposed here.

That's a fair point. I do imagine searching for dynamic libraries/filling the ABI gaps would be enough of a challenge on its own to get right, considering how things are currently done with the foreign package. I can try it as a recreational exercise, but I might not be the right person to carry that forward.

I can leave this open as a draft, but if there's anyone who would be more interested in getting this to work correctly, they can start from what I have here. I'll try to tidy up the details where I can at least. Thanks for taking a look @samth !

racket.boot is an intermediate build product that gets combined with the other boot files into the racket executable. So I'm confused about why they would be in a global store.

Just for clarity, cosmopolitan provides access to a ZIP archive embedded in the executable, it will retrieve files that are stored in it when you access anything under the /zip directory. The boot images are bundled into the final executable this way, by adding to the embedded archive with a regular zip archiving program, not in ELF sections like the normal build process does.

@shhyou shhyou added build Build failures, Makefiles, Zuo scripts, autoconf, building instructions, etc. upstream labels Jun 7, 2024
mflatt added a commit that referenced this pull request Jun 13, 2024
@mflatt
Copy link
Member

mflatt commented Jun 13, 2024

I merged the Chez Scheme part of this (by syncing with the Chez Scheme commit) and also changed the u_chars (but to unsigned char, because C89).

For the boot-file part, probably there should be a new configure option to disable embedded boot files and specify where to find them. If that sounds like something that could work, I can look into adding that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
build Build failures, Makefiles, Zuo scripts, autoconf, building instructions, etc. upstream
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants