cosmopolitan
cosmopolitan copied to clipboard
Apple's linker can't build portable binaries
Trying the example on macOS Catalina 10.15.7:
$ gcc -g -O -static -nostdlib -nostdinc -fno-pie -no-pie -mno-red-zone -o hello.com.dbg hello.c -fuse-ld=bfd -Wl,-T,ape.lds -include cosmopolitan.h crt.o ape.o cosmopolitan.a ld: unknown option: -T collect2: error: ld returned 1 exit status $ gcc -v Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/local/Cellar/gcc/10.2.0_3/libexec/gcc/x86_64-apple-darwin19/10.2.0/lto-wrapper Target: x86_64-apple-darwin19 Configured with: ../configure --build=x86_64-apple-darwin19 --prefix=/usr/local/Cellar/gcc/10.2.0_3 --libdir=/usr/local/Cellar/gcc/10.2.0_3/lib/gcc/10 --disable-nls --enable-checking=release --enable-languages=c,c++,objc,obj-c++,fortran --program-suffix=-10 --with-gmp=/usr/local/opt/gmp --with-mpfr=/usr/local/opt/mpfr --with-mpc=/usr/local/opt/libmpc --with-isl=/usr/local/opt/isl --with-system-zlib --with-pkgversion='Homebrew GCC 10.2.0_3' --with-bugurl=https://github.com/Homebrew/homebrew-core/issues --disable-multilib --with-native-system-header-dir=/usr/include --with-sysroot=/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk SED=/usr/bin/sed Thread model: posix Supported LTO compression algorithms: zlib gcc version 10.2.0 (Homebrew GCC 10.2.0_3) $ ld -v @(#)PROGRAM:ld PROJECT:ld64-609.8 BUILD 15:07:46 Dec 18 2020 configured to support archs: armv6 armv7 armv7s arm64 arm64e arm64_32 i386 x86_64 x86_64h armv6m armv7k armv7m armv7em LTO support using: LLVM version 12.0.0, (clang-1200.0.32.29) (static support for 27, runtime is 27) TAPI support using: Apple TAPI version 12.0.0 (tapi-1200.0.23.5)
It's not possible to build Actually Portable Executables if you're using a toolchain that's configured to use Apple's proprietary ld command, because Apple designed it to only produce binaries that run on Apple. You need to install an x86_64-pc-linux-gnu toolchain on your machine. The problem is I don't know if anyone's ever built a GCC+BinUtils toolchain for MacOS before. I've tried building GCC from source on Mac a couple times but failed.
I did however manage to get GCC to successfully compile on Windows: https://justine.lol/cosmopolitan/windows-compiling.html If anyone can help us do the same thing for Mac please reach out!
Until then I would recommend building your binaries on Linux. Cosmopolitan has universal deployment down pat. Universal development is a work in progress.
I use nix
to get cross-compile toolchains, and this also works on macOS. This is how I get a temporary one with nix-shell
, which automatically sets CC
, CXX
, LD
etc within the shell for you:
$ cat - > shell.nix
let pkgs = import <nixpkgs> {
crossSystem = {
config = "x86_64-pc-linux-gnu";
};
};
in
pkgs.callPackage (
{mkShell, pkg-config, zlib}:
mkShell {
nativeBuildInputs = [ pkg-config ]; # cosmopolitan build dependencies here (there aren't any?)
buildInputs = [ zlib ]; # cosmopolitan runtime dependencies here (there aren't any? qemu?)
}
) {}
^D
$ nix-shell
(From: https://nixos.wiki/wiki/Cross_Compiling#How_to_obtain_a_shell_with_a_cross_compiler )
I plan to try a macOS-only cosmopolitan build with the above and see how far I get, but for acquiring a cross gcc
toolchain for any platform (for any project), it might be useful already.
It's not possible to build Actually Portable Executables if you're using a toolchain that's configured to use Apple's proprietary ld command, because Apple designed it to only produce binaries that run on Apple. You need to install an x86_64-pc-linux-gnu toolchain on your machine. The problem is I don't know if anyone's ever built a GCC+BinUtils toolchain for MacOS before. I've tried building GCC from source on Mac a couple times but failed.
I did however manage to get GCC to successfully compile on Windows: https://justine.lol/cosmopolitan/windows-compiling.html If anyone can help us do the same thing for Mac please reach out!
Until then I would recommend building your binaries on Linux. Cosmopolitan has universal deployment down pat. Universal development is a work in progress.
But couldn't the x86_64-pc-linux-gnu toolchain be built using cosmopolitan and then it would be just as portable as any other program compiled with cosmopolitan, which of course includes macOS and Windows. How about bundling such a portable x86_64-pc-linux-gnu toolchain with cosmopolitan?
Yes it could, but it's likely blocked by #27 and also the fact that GCC is notoriously difficult to compile from source in general. I'm sure someone will come along eventually who's good at doing that. I've personally found it much more fun to develop a new compiler / assembler / linker in a greenfield. See //third_party/chibicc. That compiler will never be an adequate replacement for GCC. But it's something that's tiny fast and fun in the meantime.
blocked by #27
gcc 4.7.4 is written in pure C, only 4.8 and newer require a C++ toolchain.
I gave the x86_64-elf GNU compiler collection from homebrew a whirl and it worked 🤠 #163
@jart, I can build APE binaries on MacOS using the prebuilt / amalg pkg no problem now, but I can't seem to get any of the cosmopolitan make commands to work, not even for the hello.com build. I tried all kinds of hackery, like tweaking most of the mk config to brute replacing the third-party gcc binaries with the ones from brew. My real goal is to build redbean on MacOS, but how do I separate that task from the concerns of compiling from source, any insights / pointers?
@d4tocchini
I can't seem to get any of the cosmopolitan make commands to work
If you get
Bad system call: 12
I executed make o//tool/build/mkdeps.com o//third_party/make/make.com
on linux and copied (typically with scp but nc could also work):
o//tool/build/mkdeps.com ./build/bootstrap/mkdeps.com
and o//third_party/make/make.com ./build/bootstrap/make.com
build/bootstrap/make.com
failed with
./build/bootstrap/make.com
`make MODE= -j8 o/ape/config.h.ok` exited with 127:
o/third_party/gcc/bin/x86_64-linux-musl-gcc
so I installed x86_64-elf-gcc
as you suggested it pulled me x86_64-elf-gcc 12.1.0
and x86_64-elf-binutils 2.38
Since unbundle.com works only on linux: https://github.com/jart/cosmopolitan/blob/066ed2b2b229dce4d1f49be86179bb8efa9b9724/tool/build/unbundle.c#L75
I overwrote those lines: https://github.com/jart/cosmopolitan/blob/066ed2b2b229dce4d1f49be86179bb8efa9b9724/build/definitions.mk#L88-L99
with :'<,'>s/o\/third_party\/gcc\/bin\/x86_64-linux-musl-/x86_64-elf-/
in vim
since some warning are triggered I removed https://github.com/jart/cosmopolitan/blob/066ed2b2b229dce4d1f49be86179bb8efa9b9724/build/definitions.mk#L138
and now it fail:
libc/nexgen32e/cescapec.S: Assembler messages:
libc/nexgen32e/cescapec.S:115: Error: number of operands mismatch for `mov'
https://github.com/jart/cosmopolitan/blob/066ed2b2b229dce4d1f49be86179bb8efa9b9724/libc/nexgen32e/cescapec.S#L115
it seem to be the /2
that cause parsing failure since *2
works.
Could it be binutils regression ?
It is intended: https://sourceware.org/bugzilla/show_bug.cgi?id=4572 --divide need to be added and then libc compile fine
Thus 57 targets need to be fixed.