Skip to content

Commit 291103a

Browse files
committed
Redesign cosmocc toolchain
The `cosmocc` compiler is now being distributed as a self-contained toolchain that's path-agnostic and it no longer requires you clone the Cosmop repo to use it. The bin/ folder has been deleted from the mono repo. The `fatcosmocc` command has been renamed to `cosmocc`. MacOS support now works very well.
1 parent 3802428 commit 291103a

File tree

71 files changed

+2437
-1398
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+2437
-1398
lines changed

Makefile

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ endif
8585
ifeq ($(TOOLCHAIN),) # if TOOLCHAIN isn't defined
8686
ifeq ("$(wildcard o/third_party/gcc/bin/x86_64-linux-cosmo-*)","") # if our gcc isn't unbundled
8787
ifneq ($(UNAME_M)-$(UNAME_S), x86_64-Linux) # if this is not amd64 linux
88-
$(error you need to download https://justine.lol/cosmocc-0.0.18.zip and unzip it inside the cosmo directory)
88+
$(error you need to download https://cosmo.zip/pub/cosmocc/cosmocc-0.0.18.zip and unzip it inside the cosmo directory)
8989
endif
9090
endif
9191
endif
@@ -436,19 +436,30 @@ COSMOPOLITAN_HEADERS = \
436436
THIRD_PARTY_MUSL \
437437
THIRD_PARTY_REGEX
438438

439+
COSMOCC_HEADERS = \
440+
THIRD_PARTY_AARCH64 \
441+
THIRD_PARTY_LIBCXX \
442+
THIRD_PARTY_INTEL
443+
439444
o/$(MODE)/cosmopolitan.a: \
440445
$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_A_OBJS))
441446

442-
o/cosmopolitan.h: \
443-
o/$(MODE)/tool/build/rollup.com \
447+
o/cosmocc.h.txt: $(foreach x,$(COSMOCC_HEADERS),$($(x)_HDRS))
448+
$(file >$@, $^)
449+
450+
o/cosmopolitan.h.txt: \
451+
libc/integral/normalize.inc \
452+
$(foreach x,$(COSMOPOLITAN_HEADERS),$($(x)_HDRS))
453+
$(file >$@, $^)
454+
455+
o/cosmopolitan.h: o/cosmopolitan.h.txt \
444456
libc/integral/normalize.inc \
445457
$(foreach x,$(COSMOPOLITAN_HEADERS),$($(x)_HDRS)) \
446458
$(foreach x,$(COSMOPOLITAN_HEADERS),$($(x)_INCS))
447-
$(file >$(TMPDIR)/$(subst /,_,$@),libc/integral/normalize.inc $(foreach x,$(COSMOPOLITAN_HEADERS),$($(x)_HDRS)))
448459
@$(ECHO) '#ifndef __STRICT_ANSI__' >$@
449460
@$(ECHO) '#define _COSMO_SOURCE' >>$@
450461
@$(ECHO) '#endif' >>$@
451-
@$(COMPILE) -AROLLUP -T$@ o/$(MODE)/tool/build/rollup.com @$(TMPDIR)/$(subst /,_,$@) >>$@
462+
@$(COMPILE) -AROLLUP -T$@ build/bootstrap/rollup.com @$< >>$@
452463

453464
o/cosmopolitan.html: private .UNSANDBOXED = 1
454465
o/cosmopolitan.html: \

README.md

Lines changed: 17 additions & 291 deletions
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,17 @@ libc](https://justine.lol/cosmopolitan/index.html) website. We also have
1919

2020
## Getting Started
2121

22-
It's recommended that Cosmopolitan be installed to `/opt/cosmo` and
23-
`/opt/cosmos` on your computer. The first has the monorepo. The second
24-
contains your non-monorepo artifacts.
22+
You can start by obtaining a release of our `cosmocc` compiler from
23+
<https://cosmo.zip/pub/cosmocc/>.
2524

2625
```sh
27-
sudo mkdir -p /opt
28-
sudo chmod 1777 /opt
29-
git clone https://github.com/jart/cosmopolitan /opt/cosmo
30-
export PATH="/opt/cosmo/bin:/opt/cosmos/bin:$PATH"
31-
echo 'PATH="/opt/cosmo/bin:/opt/cosmos/bin:$PATH"' >>~/.profile
32-
ape-install # optionally install a faster systemwide ape loader
33-
cosmocc --update # pull cosmo and rebuild toolchain
26+
mkdir -p cosmocc
27+
cd cosmocc
28+
wget https://cosmo.zip/pub/cosmocc/cosmocc.zip
29+
unzip cosmocc.zip
3430
```
3531

36-
You've now successfully installed your very own cosmos. Now let's build
37-
an example program:
32+
Here's an example program we can write:
3833

3934
```c
4035
// hello.c
@@ -45,307 +40,38 @@ int main() {
4540
}
4641
```
4742

48-
To compile the program, you can run the `cosmocc` command. It's
49-
important to give it an output path that ends with `.com` so the output
50-
format will be Actually Portable Executable. When this happens, a
51-
concomitant debug binary is created automatically too.
43+
It can be compiled as follows:
5244

5345
```sh
54-
cosmocc -o hello.com hello.c
55-
./hello.com
56-
./hello.com.dbg
57-
```
58-
59-
You can use the `cosmocc` toolchain to build conventional open source
60-
projects which use autotools. This strategy normally works:
61-
62-
```sh
63-
export CC=cosmocc
64-
export CXX=cosmoc++
65-
./configure --prefix=/opt/cosmos
66-
make -j
67-
make install
46+
cosmocc -o hello hello.c
47+
./hello
6848
```
6949

7050
The Cosmopolitan Libc runtime links some heavyweight troubleshooting
7151
features by default, which are very useful for developers and admins.
7252
Here's how you can log system calls:
7353

7454
```sh
75-
./hello.com --strace
55+
./hello --strace
7656
```
7757

7858
Here's how you can get a much more verbose log of function calls:
7959

8060
```sh
81-
./hello.com --ftrace
82-
```
83-
84-
If you don't want rich runtime features like the above included, and you
85-
just want libc, and you want smaller simpler programs. In that case, you
86-
can consider using `MODE=tiny`, which is preconfigured by the repo in
87-
[build/config.mk](build/config.mk). Using this mode is much more
88-
effective at reducing binary footprint than the `-Os` flag alone. You
89-
can change your build mode by doing the following:
90-
91-
```sh
92-
export MODE=tiny
93-
cosmocc --update
94-
```
95-
96-
We can also make our program slightly smaller by using the system call
97-
interface directly, which is fine, since Cosmopolitan polyfills these
98-
interfaces across platforms, including Windows. For example:
99-
100-
```c
101-
// hello2.c
102-
#include <unistd.h>
103-
int main() {
104-
write(1, "hello world\n", 12);
105-
}
106-
```
107-
108-
Once compiled, your APE binary should be ~36kb in size.
109-
110-
```sh
111-
export MODE=tiny
112-
cosmocc -Os -o hello2.com hello2.c
113-
./hello2.com
114-
```
115-
116-
But let's say you only care about your binaries running on Linux and you
117-
don't want to use up all this additional space for platforms like WIN32.
118-
In that case, you can try `MODE=tinylinux` for example which will create
119-
executables more on the order of 8kb (similar to Musl Libc).
120-
121-
```sh
122-
export MODE=tinylinux
123-
cosmocc --update
124-
cosmocc -Os -o hello2.com hello2.c
125-
./hello2.com # <-- actually an ELF executable
126-
```
127-
128-
## ARM
129-
130-
Cosmo supports cross-compiling binaries for machines with ARM
131-
microprocessors. For example:
132-
133-
```sh
134-
make -j8 m=aarch64 o/aarch64/third_party/ggml/llama.com
135-
make -j8 m=aarch64-tiny o/aarch64-tiny/third_party/ggml/llama.com
136-
```
137-
138-
That'll produce ELF executables that run natively on two operating
139-
systems: Linux Arm64 (e.g. Raspberry Pi) and MacOS Arm64 (i.e. Apple
140-
Silicon), thus giving you full performance. The catch is you have to
141-
compile these executables on an x86_64-linux machine. The second catch
142-
is that MacOS needs a little bit of help understanding the ELF format.
143-
To solve that, we provide a tiny APE loader you can use on M1 machines.
144-
145-
```sh
146-
scp ape/ape-m1.c macintosh:
147-
scp o/aarch64/third_party/ggml/llama.com macintosh:
148-
ssh macintosh
149-
xcode-install
150-
cc -o ape ape-m1.c
151-
sudo cp ape /usr/local/bin/ape
152-
```
153-
154-
You can run your ELF AARCH64 executable on Apple Silicon as follows:
155-
156-
```sh
157-
ape ./llama.com
158-
```
159-
160-
If you want to run the `MODE=aarch64` unit tests, you need to have
161-
qemu-aarch64 installed as a binfmt_misc interpreter. It needs to be a
162-
static binary if you want it to work with Landlock Make's security. You
163-
can use the build included in our `third_party/qemu/` folder.
164-
165-
```
166-
doas cp o/third_party/qemu/qemu-aarch64 /usr/bin/qemu-aarch64
167-
doas sh -c "echo ':qemu-aarch64:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-aarch64:CF' > /proc/sys/fs/binfmt_misc/register"
168-
make -j8 m=aarch64
169-
```
170-
171-
Please note that the qemu-aarch64 binfmt_misc interpreter installation
172-
process is *essential* for being able to use the `aarch64-unknown-cosmo`
173-
toolchain to build fat APE binaries on your x86-64 machine.
174-
175-
## AMD64 + ARM64 fat APE binaries
176-
177-
If you've setup the qemu binfmt_misc interpreter, then you can can use
178-
cosmo's toolchains to build fat ape binaries. It works by compiling your
179-
program twice, so you can have a native build for both architectures in
180-
the same file. The two programs are merged together by apelink.com which
181-
also embeds multiple copies of APE loader and multiple symbols tables.
182-
183-
The easiest way to build fat APE is using `fatcosmocc`. This compiler
184-
works by creating a concomitant `.aarch64/foo.o` for every `foo.o` you
185-
compile. The only exception is the C preprocessor mode, which actually
186-
runs x86-64 GCC except with macros like `__x86_64__` undefined.
187-
188-
This toolchain works great for C projects that are written in a portable
189-
way and don't produce architecture-specific artifacts. One example of a
190-
large project that can be easily built is GNU coreutils.
191-
192-
```sh
193-
cd coreutils
194-
fatcosmocc --update ||exit
195-
./configure CC=fatcosmocc \
196-
AR=fatcosmoar \
197-
INSTALL=$(command -v fatcosmoinstall) \
198-
--prefix=/opt/cosmos \
199-
--disable-nls \
200-
--disable-dependency-tracking \
201-
--disable-silent-rules
202-
make -j8
203-
```
204-
205-
You'll then have a bunch of files like `src/ls` which are fat ape
206-
binaries. If you want to run them on Windows, then you simply need to
207-
rename the file so that it has the `.com` suffix. Better yet, consider
208-
making that a symlink (a.k.a. reparse point). The biggest gotcha with
209-
`fatcosmocc` though is ensuring builds don't strip binaries. For
210-
example, Linux's `install -s` command actually understands Windows'
211-
Portable Executable format well enough to remove the MS-DOS stub, which
212-
is where the APE shell script is stored. You need to ensure that
213-
`fatcosmoinstall` is used instead. Especially if your project needs to
214-
install the libraries built by `fatacosmoar` into `/opt/cosmos`.
215-
216-
## Advanced Fat APE Builds
217-
218-
Once you get seriously involved in creating fat APE builds of software
219-
you're going to eventually outgrow `fatcosmocc`. One example is Emacs
220-
which is trickier to build, because it produces architecture-specific
221-
files, and it also depends on shared files, e.g. zoneinfo. Since we like
222-
having everything in a neat little single-file executable container that
223-
doesn't need an "installation wizard", this tutorial will explain how we
224-
manage to accomplish that.
225-
226-
What you're going to do is, instead of using `fatcosmocc`, you're going
227-
to use both the `x86_64-unknown-cosmo-cc` and `aarch64-unknown-cosmo-cc`
228-
toolchains independently, and then run `apelink` and `zip` to manually
229-
build the final files. But there's a few tricks to learn first.
230-
231-
The first trick is to create a symlink on your system called `/zip`.
232-
Cosmopolitan Libc normally uses that as a synthetic folder that lets you
233-
access the assets in your zip executable. But since that's a read-only
234-
file system, your build system should use the normal one.
235-
236-
```sh
237-
doas ln -sf /opt/cosmos /zip
61+
./hello --ftrace
23862
```
23963

240-
Now create a file named `rebuild-fat.sh` which runs the build twice:
64+
You can use the Cosmopolitan's toolchain to build conventional open
65+
source projects which use autotools. This strategy normally works:
24166

24267
```sh
243-
#!/bin/sh
244-
set -ex
245-
export MODE=aarch64
246-
export COSMOS=/opt/cosmos/aarch64
247-
rebuild-cosmos.sh aarch64
248-
export MODE=
249-
export COSMOS=/opt/cosmos/x86_64
250-
rebuild-cosmos.sh x86_64
251-
wall.com 'finished building'
252-
```
253-
254-
Then create a second file `rebuild-cosmos.sh` which runs your build:
255-
256-
```sh
257-
#!/bin/bash
258-
set -ex
259-
260-
ARCH=${1:-x86_64}
261-
export COSMO=${COSMO:-/opt/cosmo}
262-
export COSMOS=${COSMOS:-/opt/cosmos/$ARCH}
263-
export AS=$(command -v $ARCH-unknown-cosmo-as) || exit
264-
export CC=$(command -v $ARCH-unknown-cosmo-cc) || exit
265-
export CXX=$(command -v $ARCH-unknown-cosmo-c++) || exit
266-
export AR=$(command -v $ARCH-unknown-cosmo-ar) || exit
267-
export STRIP=$(command -v $ARCH-unknown-cosmo-strip) || exit
268-
export INSTALL=$(command -v $ARCH-unknown-cosmo-install) || exit
269-
export OBJCOPY=$(command -v $ARCH-unknown-cosmo-objcopy) || exit
270-
export OBJDUMP=$(command -v $ARCH-unknown-cosmo-objdump) || exit
271-
export ADDR2LINE=$(command -v $ARCH-unknown-cosmo-addr2line) || exit
272-
273-
$CC --update
274-
275-
export COSMOPOLITAN_DISABLE_ZIPOS=1
276-
277-
cd ~/vendor/zlib
278-
./configure --prefix=$COSMOS --static
279-
make clean
280-
make -j
281-
make install
282-
283-
cd ~/vendor/ncurses-6.4
284-
./configure --prefix=$COSMOS --sysconfdir=/zip --datarootdir=/zip/share --exec-prefix=/zip/$ARCH --disable-shared
285-
make clean
286-
make -j
287-
make install
288-
289-
cd ~/vendor/readline-8.2
290-
./configure --prefix=$COSMOS --sysconfdir=/zip --datarootdir=/zip/share --exec-prefix=/zip/$ARCH --disable-shared
291-
make uninstall || true
292-
make clean
293-
make -j
294-
make install
295-
296-
# NOTES:
297-
# 1. You'll need to patch enum { FOO = x } that fails to build into a #define FOO
298-
# 2. You'll need to patch configure.ac so it DOES NOT define USABLE_FIONREAD to 1
299-
# 2. You'll need to patch configure.ac so it DOES NOT define INTERRUPT_INPUT to 1
300-
cd ~/vendor/emacs-28.2
301-
./configure --prefix=$COSMOS --sysconfdir=/zip --datarootdir=/zip/share --exec-prefix=/zip/$ARCH \
302-
--without-x --with-threads --without-gnutls --disable-silent-rules --with-file-notification=no
303-
make uninstall || true
304-
make clean
68+
export CC=x86_64-unknown-cosmo-cc
69+
export CXX=x86_64-unknown-cosmo-c++
70+
./configure --prefix=/opt/cosmos/x86_64
30571
make -j
30672
make install
30773
```
30874

309-
Once you've completed this build process, you'll have the ELF files
310-
`/opt/cosmos/x86_64/bin/emacs` and `/opt/cosmos/aarch64/bin/emacs`. Your
311-
next move is to combine them into a single pristine `emacs.com` file.
312-
313-
```sh
314-
cd /zip
315-
COSMO=${COSMO:-/opt/cosmo}
316-
mkdir -p /opt/cosmos/bin
317-
apelink \
318-
-o /opt/cosmos/bin/emacs.com \
319-
-l "$COSMO/o//ape/ape.elf" \
320-
-l "$COSMO/o/aarch64/ape/ape.elf" \
321-
-M "$COSMO/ape/ape-m1.c" \
322-
/opt/cosmos/x86_64/bin/emacs \
323-
/opt/cosmos/aarch64/bin/emacs
324-
cd /zip
325-
zip -r /opt/cosmos/bin/emacs.com \
326-
aarch64/libexec \
327-
x86_64/libexec \
328-
share/terminfo \
329-
$(find share/emacs -type f |
330-
grep -v '\.el.gz$' |
331-
grep -v refcards |
332-
grep -v images)
333-
```
334-
335-
You can now scp your `emacs.com` build to seven operating systems for
336-
two distinct kinds of microprocessors without any dependencies. All the
337-
LISP, zoneinfo, and termcap files it needs are stored inside the ZIP
338-
structure of the binary, which has performance that's equivalent to the
339-
Linux filesystem (even though it decompresses artifacts on the fly!) For
340-
this reason, you might actually find that fat APE Emacs goes faster if
341-
you're using an operating system like Windows where files are go slow.
342-
343-
If you like to use Vim instead of Emacs, then you can build that too.
344-
However Vim's build system makes it a bit harder, since it's configured
345-
to always strip binaries. The `apelink` program needs the symbol tables
346-
to still be there when it creates the fat version. Otherwise tools like
347-
`--ftrace` won't work.
348-
34975
## Monolithic Source Builds
35076

35177
Cosmopolitan can be compiled from source on any Linux distro. First, you

0 commit comments

Comments
 (0)