From d53c335a459c1f5c7955686a8fd1c3b7c9deefc0 Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Fri, 11 Aug 2023 22:52:11 -0700 Subject: [PATCH] Introduce new fatcosmocc command This new script is an alternative to the `cosmocc` command. It's still a work in progress. It abstracts all the gory details of building separate copies of your executable and then running the apelink.com program. --- Makefile | 49 +++-- README.md | 53 +++-- ape/apeinstall.sh | 124 +----------- ape/apeuninstall.sh | 50 +---- bin/ape-install | 132 ++++++++++++ bin/ape-uninstall | 58 ++++++ bin/cosmoc++ | 1 + {tool/scripts => bin}/cosmocc | 151 +++++++++----- bin/fatcosmoc++ | 1 + bin/fatcosmocc | 310 +++++++++++++++++++++++++++++ bin/unknown-unknown-cosmo-ar | 1 + bin/unknown-unknown-cosmo-c++ | 1 + bin/unknown-unknown-cosmo-cc | 1 + bin/unknown-unknown-cosmo-g++ | 1 + bin/unknown-unknown-cosmo-gcc | 1 + bin/x86_64-unknown-cosmo-addr2line | 13 ++ bin/x86_64-unknown-cosmo-ar | 18 ++ bin/x86_64-unknown-cosmo-as | 13 ++ bin/x86_64-unknown-cosmo-c++ | 1 + bin/x86_64-unknown-cosmo-cc | 1 + bin/x86_64-unknown-cosmo-g++ | 1 + bin/x86_64-unknown-cosmo-gcc | 1 + bin/x86_64-unknown-cosmo-ld | 13 ++ bin/x86_64-unknown-cosmo-objcopy | 13 ++ bin/x86_64-unknown-cosmo-strip | 13 ++ build/definitions.mk | 8 +- libc/stdio/putwc_unlocked.c | 2 +- libc/stdio/rand.h | 10 +- tool/build/apelink.c | 110 +++++++--- tool/build/march-native.c | 184 +++++++++++++++++ tool/hello/hello.mk | 4 +- tool/scripts/cosmoc++ | 216 -------------------- tool/scripts/fat-aarch64 | 51 +++++ tool/scripts/fat-x86_64 | 56 ++++++ tool/scripts/setup-cosmos | 14 ++ 35 files changed, 1151 insertions(+), 525 deletions(-) mode change 100755 => 120000 ape/apeinstall.sh mode change 100755 => 120000 ape/apeuninstall.sh create mode 100755 bin/ape-install create mode 100755 bin/ape-uninstall create mode 120000 bin/cosmoc++ rename {tool/scripts => bin}/cosmocc (52%) create mode 120000 bin/fatcosmoc++ create mode 100755 bin/fatcosmocc create mode 100755 bin/unknown-unknown-cosmo-ar create mode 120000 bin/unknown-unknown-cosmo-c++ create mode 120000 bin/unknown-unknown-cosmo-cc create mode 120000 bin/unknown-unknown-cosmo-g++ create mode 120000 bin/unknown-unknown-cosmo-gcc create mode 100755 bin/x86_64-unknown-cosmo-addr2line create mode 100755 bin/x86_64-unknown-cosmo-ar create mode 100755 bin/x86_64-unknown-cosmo-as create mode 120000 bin/x86_64-unknown-cosmo-c++ create mode 120000 bin/x86_64-unknown-cosmo-cc create mode 120000 bin/x86_64-unknown-cosmo-g++ create mode 120000 bin/x86_64-unknown-cosmo-gcc create mode 100755 bin/x86_64-unknown-cosmo-ld create mode 100755 bin/x86_64-unknown-cosmo-objcopy create mode 100755 bin/x86_64-unknown-cosmo-strip create mode 100644 tool/build/march-native.c delete mode 100755 tool/scripts/cosmoc++ create mode 100755 tool/scripts/fat-aarch64 create mode 100755 tool/scripts/fat-x86_64 create mode 100755 tool/scripts/setup-cosmos diff --git a/Makefile b/Makefile index ceef06b66..95929467e 100644 --- a/Makefile +++ b/Makefile @@ -424,27 +424,42 @@ $(SRCS): \ libc/integral/lp64arg.inc \ libc/integral/lp64.inc -.PHONY: toolchain ifeq ($(ARCH), x86_64) -toolchain: o/cosmopolitan.h \ - o/$(MODE)/ape/public/ape.lds \ - o/$(MODE)/libc/crt/crt.o \ - o/$(MODE)/ape/ape.o \ - o/$(MODE)/ape/ape-copy-self.o \ - o/$(MODE)/ape/ape-no-modify-self.o \ - o/$(MODE)/cosmopolitan.a \ - o/$(MODE)/third_party/libcxx/libcxx.a \ - o/$(MODE)/tool/build/fixupobj.com \ - o/$(MODE)/tool/build/zipcopy.com +TOOLCHAIN_ARTIFACTS = \ + o/cosmopolitan.h \ + o/$(MODE)/ape/public/ape.lds \ + o/$(MODE)/libc/crt/crt.o \ + o/$(MODE)/ape/ape.elf \ + o/$(MODE)/ape/ape.o \ + o/$(MODE)/ape/ape-copy-self.o \ + o/$(MODE)/ape/ape-no-modify-self.o \ + o/$(MODE)/cosmopolitan.a \ + o/$(MODE)/third_party/libcxx/libcxx.a \ + o/$(MODE)/tool/build/march-native.com \ + o/$(MODE)/tool/build/ar.com \ + o/$(MODE)/tool/build/fixupobj.com \ + o/$(MODE)/tool/build/zipcopy.com \ + o/$(MODE)/tool/build/apelink.com \ + o/$(MODE)/tool/build/pecheck.com else -toolchain: o/$(MODE)/ape/aarch64.lds \ - o/$(MODE)/libc/crt/crt.o \ - o/$(MODE)/cosmopolitan.a \ - o/$(MODE)/third_party/libcxx/libcxx.a \ - o/$(MODE)/tool/build/fixupobj.com \ - o/$(MODE)/tool/build/zipcopy.com +TOOLCHAIN_ARTIFACTS = \ + o/$(MODE)/ape/ape.elf \ + o/$(MODE)/ape/aarch64.lds \ + o/$(MODE)/libc/crt/crt.o \ + o/$(MODE)/cosmopolitan.a \ + o/$(MODE)/third_party/libcxx/libcxx.a \ + o/$(MODE)/tool/build/march-native.com \ + o/$(MODE)/tool/build/fixupobj.com \ + o/$(MODE)/tool/build/zipcopy.com endif +.PHONY: toolchain +toolchain: $(TOOLCHAIN_ARTIFACTS) + +.PHONY: clean_toolchain +clean_toolchain: + $(RM) $(TOOLCHAIN_ARTIFACTS) + aarch64: private .INTERNET = true aarch64: private .UNSANDBOXED = true aarch64: diff --git a/README.md b/README.md index acc04989b..effbcd85f 100644 --- a/README.md +++ b/README.md @@ -27,14 +27,10 @@ contains your non-monorepo artifacts. sudo mkdir -p /opt sudo chmod 1777 /opt git clone https://github.com/jart/cosmopolitan /opt/cosmo -cd /opt/cosmo -make -j8 toolchain -ape/apeinstall.sh # optional -mkdir -p /opt/cosmos/bin -export PATH="/opt/cosmos/bin:$PATH" -echo 'PATH="/opt/cosmos/bin:$PATH"' >>~/.profile -sudo ln -sf /opt/cosmo/tool/scripts/cosmocc /opt/cosmos/bin/cosmocc -sudo ln -sf /opt/cosmo/tool/scripts/cosmoc++ /opt/cosmos/bin/cosmoc++ +export PATH="/opt/cosmo/bin:/opt/cosmos/bin:$PATH" +echo 'PATH="/opt/cosmo/bin:/opt/cosmos/bin:$PATH"' >>~/.profile +cosmocc --update # pull cosmo and rebuild toolchain +ape-install # [optional] install /usr/bin/ape and binfmt_misc ``` You've now successfully installed your very own cosmos. Now let's build @@ -88,21 +84,21 @@ Here's how you can get a much more verbose log of function calls: ./hello.com --ftrace ``` -If you want to cut out the bloat and instead make your executables as -tiny as possible, then the monorepo supports numerous build modes. You -can select one of the predefined ones by looking at -[build/config.mk](build/config.mk). One of the most popular modes is -`MODE=tiny`. It can be used with the `cosmocc` toolchain as follows: +If you don't want rich runtime features like the above included, and you +just want libc, and you want smaller simpler programs. In that case, you +can consider using `MODE=tiny`, which is preconfigured by the repo in +[build/config.mk](build/config.mk). Using this mode is much more +effective at reducing binary footprint than the `-Os` flag alone. You +can change your build mode by doing the following: ```sh -cd /opt/cosmo -make -j8 MODE=tiny toolchain +export MODE=tiny +cosmocc --update ``` -Now that we have our toolchain, let's write a program that links less -surface area than the program above. The executable that this program -produces will run on platforms like Linux, Windows, MacOS, etc., even -though it's directly using POSIX APIs, which Cosmopolitan polyfills. +We can also make our program slightly smaller by using the system call +interface directly, which is fine, since Cosmopolitan polyfills these +interfaces across platforms, including Windows. For example: ```c // hello2.c @@ -112,8 +108,7 @@ int main() { } ``` -Now let's compile our tiny actually portable executable, which should be -on the order of 20kb in size. +Once compiled, your APE binary should be ~36kb in size. ```sh export MODE=tiny @@ -121,14 +116,14 @@ cosmocc -Os -o hello2.com hello2.c ./hello2.com ``` -Let's say you only care about Linux and would rather have simpler tinier -binaries, similar to what Musl Libc would produce. In that case, try -using the `MODE=tinylinux` build mode, which can produce binaries more -on the order of 4kb. +But let's say you only care about your binaries running on Linux and you +don't want to use up all this additional space for platforms like WIN32. +In that case, you can try `MODE=tinylinux` for example which will create +executables more on the order of 8kb (similar to Musl Libc). ```sh export MODE=tinylinux -(cd /opt/cosmo; make -j8 toolchain) +cosmocc --update cosmocc -Os -o hello2.com hello2.c ./hello2.com # <-- actually an ELF executable ``` @@ -207,7 +202,7 @@ WINE installed to `binfmt_misc`. You can fix that by installing the the APE loader as an interpreter. It'll improve build performance too! ```sh -ape/apeinstall.sh +bin/ape-install ``` Since the Cosmopolitan repository is very large, you might only want to @@ -306,11 +301,11 @@ It's possible to install the APE loader systemwide as follows. # for Linux, Darwin, and BSDs # 1. Copies APE Loader to /usr/bin/ape # 2. Registers w/ binfmt_misc too if Linux -ape/apeinstall.sh +bin/ape-install # System-Wide APE Uninstall # for Linux, Darwin, and BSDs -ape/apeuninstall.sh +bin/ape-uninstall ``` It's also possible to convert APE binaries into the system-local format diff --git a/ape/apeinstall.sh b/ape/apeinstall.sh deleted file mode 100755 index 7744420aa..000000000 --- a/ape/apeinstall.sh +++ /dev/null @@ -1,123 +0,0 @@ -#!/bin/sh - -if [ "$(id -u)" -eq 0 ]; then - SUDO= -else - SUDO=sudo -fi - -echo "Actually Portable Executable (APE) Installer" >&2 -echo "Author: Justine Tunney " >&2 - -################################################################################ -# INSTALL APE LOADER SYSTEMWIDE - -if [ -f o/depend ] && make -j8 o//ape; then - echo "successfully recompiled ape loader" >&2 -elif [ -d build/bootstrap ]; then - # if make isn't being used then it's unlikely the user changed the sources - # in that case the prebuilt binaries should be completely up-to-date - echo "using prebuilt ape loader from cosmo repo" >&2 - mkdir -p o//ape || exit - cp -af build/bootstrap/ape.elf o//ape/ape.elf || exit - cp -af build/bootstrap/ape.macho o//ape/ape.macho || exit -else - echo "no cosmopolitan libc repository here" >&2 - echo "fetching ape loader from justine.lol" >&2 - mkdir -p o//ape || exit - if command -v wget >/dev/null 2>&1; then - wget -qO o//ape/ape.elf https://justine.lol/ape.elf || exit - wget -qO o//ape/ape.macho https://justine.lol/ape.macho || exit - else - curl -Rso o//ape/ape.elf https://justine.lol/ape.elf || exit - curl -Rso o//ape/ape.macho https://justine.lol/ape.macho || exit - fi - chmod +x o//ape/ape.elf || exit - chmod +x o//ape/ape.macho || exit -fi - -if [ "$(uname -s)" = "Darwin" ]; then - if ! [ /usr/bin/ape -nt o//ape/ape.macho ]; then - echo >&2 - echo "installing o//ape/ape.elf to /usr/bin/ape" >&2 - echo "$SUDO mv -f o//ape/ape.elf /usr/bin/ape" >&2 - $SUDO cp -f o//ape/ape.macho /usr/bin/ape || exit - echo "done" >&2 - fi -else - if ! [ /usr/bin/ape -nt o//ape/ape.elf ]; then - echo >&2 - echo "installing o//ape/ape.elf to /usr/bin/ape" >&2 - echo "$SUDO mv -f o//ape/ape.elf /usr/bin/ape" >&2 - $SUDO cp -f o//ape/ape.elf /usr/bin/ape || exit - echo "done" >&2 - fi -fi - -################################################################################ -# REGISTER APE LOADER WITH BINFMT_MISC TOO (LINUX-ONLY) - -if [ x"$(uname -s)" = xLinux ]; then - - if [ -e /proc/sys/fs/binfmt_misc/APE ]; then - echo >&2 - echo it looks like APE is already registered with binfmt_misc >&2 - echo To reinstall please run ape/apeuninstall.sh first >&2 - echo please check that it is mapped to ape not /bin/sh >&2 - echo cat /proc/sys/fs/binfmt_misc/APE >&2 - cat /proc/sys/fs/binfmt_misc/APE >&2 - exit - fi - - if ! [ -e /proc/sys/fs/binfmt_misc ]; then - echo >&2 - echo loading binfmt_misc into your kernel >&2 - echo you may need to edit configs to persist across reboot >&2 - echo $SUDO modprobe binfmt_misc >&2 - $SUDO modprobe binfmt_misc || exit - echo done >&2 - fi - - if ! [ -e /proc/sys/fs/binfmt_misc/register ]; then - echo >&2 - echo mounting binfmt_misc into your kernel >&2 - echo you may need to edit configs to persist across reboot >&2 - echo $SUDO mount -t binfmt_misc none /proc/sys/fs/binfmt_misc >&2 - $SUDO mount -t binfmt_misc none /proc/sys/fs/binfmt_misc || exit - echo done >&2 - fi - - echo >&2 - echo registering APE with binfmt_misc >&2 - echo you may need to edit configs to persist across reboot >&2 - echo '$SUDO sh -c "echo '"'"':APE:M::MZqFpD::/usr/bin/ape:'"'"' >/proc/sys/fs/binfmt_misc/register"' >&2 - $SUDO sh -c "echo ':APE:M::MZqFpD::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register" || exit - echo '$SUDO sh -c "echo '"'"':APE-jart:M::jartsr::/usr/bin/ape:'"'"' >/proc/sys/fs/binfmt_misc/register"' >&2 - $SUDO sh -c "echo ':APE-jart:M::jartsr::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register" || exit - echo done >&2 - - if [ x"$(cat /proc/sys/fs/binfmt_misc/status)" = xdisabled ]; then - echo >&2 - echo enabling binfmt_misc >&2 - echo you may need to edit configs to persist across reboot >&2 - echo $SUDO sh -c 'echo 1 >/proc/sys/fs/binfmt_misc/status' >&2 - $SUDO sh -c 'echo 1 >/proc/sys/fs/binfmt_misc/status' || exit - echo done >&2 - fi - -fi - -################################################################################ - -{ - echo - echo "------------------------------------------------------------------" - echo - echo "APE INSTALL COMPLETE" - echo - echo "If you decide to uninstall APE later on" - echo "you may do so using ape/apeuninstall.sh" - echo - echo "Enjoy your APE loader (>'.')>" - echo -} >&2 diff --git a/ape/apeinstall.sh b/ape/apeinstall.sh new file mode 120000 index 000000000..43a7f505e --- /dev/null +++ b/ape/apeinstall.sh @@ -0,0 +1 @@ +../bin/ape-install \ No newline at end of file diff --git a/ape/apeuninstall.sh b/ape/apeuninstall.sh deleted file mode 100755 index 2274462de..000000000 --- a/ape/apeuninstall.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/sh - -if [ "$UID" = "0" ]; then - SUDO= -else - SUDO=sudo -fi - -{ - echo - echo "APE Uninstaller intends to run (in pseudo-shell)" - echo - echo " sudo echo -1 into /proc/sys/fs/binfmt_misc/APE*" - echo " sudo rm -f /usr/bin/ape ~/.ape /tmp/.ape # etc." - echo - echo "You may then use ape/apeinstall.sh to reinstall it" - echo -} >&2 - -set -ex -for f in /proc/sys/fs/binfmt_misc/APE*; do - if [ -f $f ]; then - $SUDO sh -c "echo -1 >$f" || exit - fi -done - -# system installation -if [ -f /usr/bin/ape ]; then - $SUDO rm -f /usr/bin/ape -fi - -# legacy installations -rm -f o/tmp/ape /tmp/ape "${TMPDIR:-/tmp}/ape" - -# ad-hoc installations -for x in .ape \ - .ape-1.1 \ - .ape-1.3 \ - .ape-1.4 \ - .ape-1.5 \ - .ape-1.6 \ - .ape-blink-0.9.2 \ - .ape-blink-1.0.0; do - rm -f \ - ~/$x \ - /tmp/$x \ - o/tmp/$x \ - "${TMPDIR:-/tmp}/$x" -done diff --git a/ape/apeuninstall.sh b/ape/apeuninstall.sh new file mode 120000 index 000000000..bed625ce8 --- /dev/null +++ b/ape/apeuninstall.sh @@ -0,0 +1 @@ +../bin/ape-uninstall \ No newline at end of file diff --git a/bin/ape-install b/bin/ape-install new file mode 100755 index 000000000..2552a1f4a --- /dev/null +++ b/bin/ape-install @@ -0,0 +1,132 @@ +#!/bin/sh + +PROG=${0##*/} +MODE=${MODE:-$m} +COSMO=${COSMO:-/opt/cosmo} +COSMOS=${COSMOS:-/opt/cosmos} + +if [ ! -f ape/loader.c ]; then + cd "$COSMO" || exit +fi + +if [ "$(id -u)" -eq 0 ]; then + SUDO= +else + SUDO=sudo +fi + +echo "Actually Portable Executable (APE) Installer" >&2 +echo "Author: Justine Tunney " >&2 + +################################################################################ +# INSTALL APE LOADER SYSTEMWIDE + +if [ -f o/depend ] && make -j8 o//ape; then + echo "successfully recompiled ape loader" >&2 +elif [ -d build/bootstrap ]; then + # if make isn't being used then it's unlikely the user changed the sources + # in that case the prebuilt binaries should be completely up-to-date + echo "using prebuilt ape loader from cosmo repo" >&2 + mkdir -p o//ape || exit + cp -af build/bootstrap/ape.elf o//ape/ape.elf || exit + cp -af build/bootstrap/ape.macho o//ape/ape.macho || exit +else + echo "no cosmopolitan libc repository here" >&2 + echo "fetching ape loader from justine.lol" >&2 + mkdir -p o//ape || exit + if command -v wget >/dev/null 2>&1; then + wget -qO o//ape/ape.elf https://justine.lol/ape.elf || exit + wget -qO o//ape/ape.macho https://justine.lol/ape.macho || exit + else + curl -Rso o//ape/ape.elf https://justine.lol/ape.elf || exit + curl -Rso o//ape/ape.macho https://justine.lol/ape.macho || exit + fi + chmod +x o//ape/ape.elf || exit + chmod +x o//ape/ape.macho || exit +fi + +if [ "$(uname -s)" = "Darwin" ]; then + if ! [ /usr/bin/ape -nt o//ape/ape.macho ]; then + echo >&2 + echo "installing o//ape/ape.elf to /usr/bin/ape" >&2 + echo "$SUDO mv -f o//ape/ape.elf /usr/bin/ape" >&2 + $SUDO cp -f o//ape/ape.macho /usr/bin/ape || exit + echo "done" >&2 + fi +else + if ! [ /usr/bin/ape -nt o//ape/ape.elf ]; then + echo >&2 + echo "installing o//ape/ape.elf to /usr/bin/ape" >&2 + echo "$SUDO mv -f o//ape/ape.elf /usr/bin/ape" >&2 + $SUDO cp -f o//ape/ape.elf /usr/bin/ape || exit + echo "done" >&2 + fi +fi + +################################################################################ +# REGISTER APE LOADER WITH BINFMT_MISC TOO (LINUX-ONLY) + +if [ x"$(uname -s)" = xLinux ]; then + + if [ -e /proc/sys/fs/binfmt_misc/APE ]; then + echo >&2 + echo it looks like APE is already registered with binfmt_misc >&2 + echo To reinstall please run ape/apeuninstall.sh first >&2 + echo please check that it is mapped to ape not /bin/sh >&2 + echo cat /proc/sys/fs/binfmt_misc/APE >&2 + cat /proc/sys/fs/binfmt_misc/APE >&2 + exit + fi + + if ! [ -e /proc/sys/fs/binfmt_misc ]; then + echo >&2 + echo loading binfmt_misc into your kernel >&2 + echo you may need to edit configs to persist across reboot >&2 + echo $SUDO modprobe binfmt_misc >&2 + $SUDO modprobe binfmt_misc || exit + echo done >&2 + fi + + if ! [ -e /proc/sys/fs/binfmt_misc/register ]; then + echo >&2 + echo mounting binfmt_misc into your kernel >&2 + echo you may need to edit configs to persist across reboot >&2 + echo $SUDO mount -t binfmt_misc none /proc/sys/fs/binfmt_misc >&2 + $SUDO mount -t binfmt_misc none /proc/sys/fs/binfmt_misc || exit + echo done >&2 + fi + + echo >&2 + echo registering APE with binfmt_misc >&2 + echo you may need to edit configs to persist across reboot >&2 + echo '$SUDO sh -c "echo '"'"':APE:M::MZqFpD::/usr/bin/ape:'"'"' >/proc/sys/fs/binfmt_misc/register"' >&2 + $SUDO sh -c "echo ':APE:M::MZqFpD::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register" || exit + echo '$SUDO sh -c "echo '"'"':APE-jart:M::jartsr::/usr/bin/ape:'"'"' >/proc/sys/fs/binfmt_misc/register"' >&2 + $SUDO sh -c "echo ':APE-jart:M::jartsr::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register" || exit + echo done >&2 + + if [ x"$(cat /proc/sys/fs/binfmt_misc/status)" = xdisabled ]; then + echo >&2 + echo enabling binfmt_misc >&2 + echo you may need to edit configs to persist across reboot >&2 + echo $SUDO sh -c 'echo 1 >/proc/sys/fs/binfmt_misc/status' >&2 + $SUDO sh -c 'echo 1 >/proc/sys/fs/binfmt_misc/status' || exit + echo done >&2 + fi + +fi + +################################################################################ + +{ + echo + echo "------------------------------------------------------------------" + echo + echo "APE INSTALL COMPLETE" + echo + echo "If you decide to uninstall APE later on" + echo "you may do so using ape/apeuninstall.sh" + echo + echo "Enjoy your APE loader (>'.')>" + echo +} >&2 diff --git a/bin/ape-uninstall b/bin/ape-uninstall new file mode 100755 index 000000000..e50d8b60e --- /dev/null +++ b/bin/ape-uninstall @@ -0,0 +1,58 @@ +#!/bin/sh + +PROG=${0##*/} +MODE=${MODE:-$m} +COSMO=${COSMO:-/opt/cosmo} +COSMOS=${COSMOS:-/opt/cosmos} + +if [ ! -f ape/loader.c ]; then + cd "$COSMO" || exit +fi + +if [ "$UID" = "0" ]; then + SUDO= +else + SUDO=sudo +fi + +{ + echo + echo "APE Uninstaller intends to run (in pseudo-shell)" + echo + echo " sudo echo -1 into /proc/sys/fs/binfmt_misc/APE*" + echo " sudo rm -f /usr/bin/ape ~/.ape /tmp/.ape # etc." + echo + echo "You may then use ape/apeinstall.sh to reinstall it" + echo +} >&2 + +set -ex +for f in /proc/sys/fs/binfmt_misc/APE*; do + if [ -f $f ]; then + $SUDO sh -c "echo -1 >$f" || exit + fi +done + +# system installation +if [ -f /usr/bin/ape ]; then + $SUDO rm -f /usr/bin/ape +fi + +# legacy installations +rm -f o/tmp/ape /tmp/ape "${TMPDIR:-/tmp}/ape" + +# ad-hoc installations +for x in .ape \ + .ape-1.1 \ + .ape-1.3 \ + .ape-1.4 \ + .ape-1.5 \ + .ape-1.6 \ + .ape-blink-0.9.2 \ + .ape-blink-1.0.0; do + rm -f \ + ~/$x \ + /tmp/$x \ + o/tmp/$x \ + "${TMPDIR:-/tmp}/$x" +done diff --git a/bin/cosmoc++ b/bin/cosmoc++ new file mode 120000 index 000000000..978d77998 --- /dev/null +++ b/bin/cosmoc++ @@ -0,0 +1 @@ +cosmocc \ No newline at end of file diff --git a/tool/scripts/cosmocc b/bin/cosmocc similarity index 52% rename from tool/scripts/cosmocc rename to bin/cosmocc index 11073d930..5234f328f 100755 --- a/tool/scripts/cosmocc +++ b/bin/cosmocc @@ -1,17 +1,14 @@ #!/bin/sh # -# cosmopolitan c compiler +# non-fat cosmopolitan c compiler # # getting started # # sudo chmod 1777 /opt # git clone https://github.com/jart/cosmopolitan /opt/cosmo -# (cd /opt/cosmo; make -j8 toolchain) -# sudo ln -sf /opt/cosmo/tool/scripts/cosmocc /usr/local/bin/cosmocc -# sudo ln -sf /opt/cosmo/tool/scripts/cosmoc++ /usr/local/bin/cosmoc++ -# cosmocc -o hello.com hello.c -# ./foo.com -# ./foo.com.dbg +# export PATH="$PATH:/opt/cosmo/bin:/opt/cosmos/bin" +# echo 'export PATH="$PATH:/opt/cosmo/bin:/opt/cosmos/bin"' >>~/.profile +# cosmocc --update # pull and rebuild toolchain artifacts # # building open source projects # @@ -53,13 +50,14 @@ # cosmocc -o foo.com foo.c # +PROG=${0##*/} MODE=${MODE:-$m} COSMO=${COSMO:-/opt/cosmo} COSMOS=${COSMOS:-/opt/cosmos} if [ "$1" = "--version" ]; then -cat <<'EOF' -x86_64-unknown-cosmo-gcc (GCC) 11.2.0 +cat <&2 + "$GIT" pull --quiet || exit + fi + echo "$PROG: building cosmo x86_64 toolchain..." >&2 + make --silent -j toolchain MODE="${MODE}" || exit + "$COSMO/tool/scripts/setup-cosmos" + echo "$PROG: successfully updated your cosmo toolchain" >&2 + exit +fi + +CC="$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-gcc" ORIGINAL="$0 $*" PLATFORM="-D__COSMOPOLITAN__" PREDEF="-include libc/integral/normalize.inc" CCFLAGS="-fdata-sections -ffunction-sections -fno-pie -mno-tls-direct-seg-refs -mno-red-zone -fportcosmo" -CFLAGS= CPPFLAGS="-nostdinc -iquote $COSMO -isystem $COSMOS/include -isystem $COSMO/libc/isystem" LDFLAGS="-static -no-pie -nostdlib -fuse-ld=bfd -Wl,-melf_x86_64" APEFLAGS="-L$COSMOS/lib -Wl,--gc-sections -Wl,-T,$COSMO/o/$MODE/ape/public/ape.lds $COSMO/o/$MODE/ape/ape-no-modify-self.o $COSMO/o/$MODE/libc/crt/crt.o" LDLIBS="$COSMO/o/$MODE/cosmopolitan.a" -CC="$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-gcc" -STRIP="$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-strip" -OBJCOPY="$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-objcopy" -FIXUPOBJ="$COSMO/o/$MODE/tool/build/fixupobj.com" -ZIPCOPY="$COSMO/o/$MODE/tool/build/zipcopy.com" +if [ x"$0" != x"${0%++}" ]; then + CC="$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-g++" + CCFLAGS="$CCFLAGS -fno-rtti -fno-exceptions -fuse-cxa-atexit -fno-threadsafe-statics" + LDLIBS="$COSMO/o/$MODE/third_party/libcxx/libcxx.a $LDLIBS" +fi if [ ! -d "$COSMO" ]; then - echo "you need to checkout cosmopolitan to your $COSMO directory" >&2 + echo "$PROG: you need to clone cosmopolitan to your $COSMO directory" >&2 exit 1 fi -if [ ! -d "$COSMOS" ]; then - echo "you need to create your $COSMOS directory" >&2 - exit 1 -fi - -if [ ! -f "$CC" ] || - [ ! -f "$OBJCOPY" ] || - [ ! -f "$FIXUPOBJ" ] || - [ ! -f "$ZIPCOPY" ]; then - echo "error: cosmopolitan artifacts missing; please run" >&2 - echo " cd $COSMOS" >&2 - echo " make -j8 m=$MODE toolchain" >&2 +if [ ! -d "$COSMOS" ] || + [ ! -x "$COSMO/o/$MODE/cosmopolitan.a" ]; then + echo "$PROG: you need to run: $PROG --update" >&2 exit 1 fi @@ -118,21 +120,23 @@ FIRST=1 OUTPUT= SFLAG=0 INTENT=ld +GOT_SOME=0 NEED_OUTPUT= RELOCATABLE=0 -FRAME=-fno-omit-frame-pointer for x; do if [ $FIRST -eq 1 ]; then set -- FIRST=0 fi - if [ x"$x" = x"-Werror" ]; then - # this toolchain is intended for building other people's code - # elevating warnings into errors, should only be done by devs + if [ -n "$NEED_OUTPUT" ]; then + NEED_OUTPUT= + OUTPUT=$x + set -- "$@" "$x" continue - elif [ x"$x" = x"-pedantic" ]; then - # this toolchain is intended for building other people's code - # we don't need the compiler's assistance to be more portable + fi + if [ x"$x" = x"${x#-*}" ]; then + GOT_SOME=1 + elif [ x"$x" = x"-static-libstdc++" ]; then continue elif [ x"$x" = x"-static-libgcc" ]; then continue @@ -151,23 +155,50 @@ for x; do NEED_OUTPUT=1 elif [ x"$x" != x"${x#-o}" ]; then OUTPUT=${x#-o} - elif [ -n "$NEED_OUTPUT" ]; then - NEED_OUTPUT= - OUTPUT=$x elif [ x"$x" = x"-fpic" ]; then continue elif [ x"$x" = x"-fPIC" ]; then continue - elif [ x"$x" = x"-shared" ]; then - echo "error: cosmocc -shared isn't supported" >&2 + elif [ x"$x" = x"-r" ] || + [ x"$x" = x"-pie" ] || + [ x"$x" = x"-frtti" ] || + [ x"$x" = x"-shared" ] || + [ x"$x" = x"-nostdlib" ] || + [ x"$x" = x"-mred-zone" ] || + [ x"$x" = x"-fexceptions" ] || + [ x"$x" = x"-fsanitize=thread" ]; then + echo "$PROG: $x not supported" >&2 exit 1 - elif [ x"$x" = x"-fomit-frame-pointer" ] || [ x"$x" = x"-fno-omit-frame-pointer" ]; then - FRAME=$x + elif [ x"$x" = x"-fsanitize=all" ] || + [ x"$x" = x"-fsanitize=address" ] || + [ x"$x" = x"-fsanitize=undefined" ]; then + echo "$PROG: use cosmo MODE=dbg rather than passing $x" >&2 + exit 1 + elif [ x"$x" = x"-fomit-frame-pointer" ]; then + # Quoth Apple "The frame pointer register must always address a + # valid frame record. Some functions — such as leaf functions or + # tail calls — may opt not to create an entry in this list. As a + # result, stack traces are always meaningful, even without debug + # information." + x="-momit-leaf-frame-pointer" + elif [ x"$x" = x"-Werror" ] || \ + [ x"$x" = x"-pedantic-errors" ]; then + # this toolchain is intended for building other people's code + # elevating warnings into errors, should only be done by devs + continue + elif [ x"$x" = x"-march=native" ]; then + set -- "$@" $("$COSMO/o/$MODE/tool/build/march-native.com") continue fi set -- "$@" "$x" done +if [ "$GOT_SOME" -eq 0 ]; then + echo "$PROG: fatal error: no input files" >&2 + echo "compilation terminated." >&2 + exit 1 +fi + if [ $RELOCATABLE -eq 1 ]; then APEFLAGS="-r" fi @@ -178,25 +209,39 @@ fi if [ x"$OPT" != x"-Os" ] && [ x"${MODE#tiny}" != x"${MODE}" ]; then # support --ftrace unless optimizing for size - CFLAGS="$CFLAGS -fpatchable-function-entry=18,16" + CCFLAGS="$CCFLAGS -fpatchable-function-entry=18,16" +fi + +if [ x"$MODE" = x"dbg" ]; then + set -- \ + -fsanitize=address \ + -fsanitize=undefined \ + "$@" +fi + +if [ x"$OPT" != x"-Os" ] && + [ x"${MODE#tiny}" != x"${MODE}" ]; then + set -- \ + -fno-optimize-sibling-calls \ + -mno-omit-leaf-frame-pointer \ + "$@" fi if [ $INTENT = cpp ]; then - set -- $PLATFORM $CCFLAGS $CPPFLAGS "$@" + set -- "$CC" $PLATFORM $CCFLAGS $CPPFLAGS "$@" elif [ $INTENT = cc ]; then - set -- $PLATFORM $PREDEF $CCFLAGS $CFLAGS $CPPFLAGS "$@" $FRAME + set -- "$CC" $PLATFORM $PREDEF $CCFLAGS $CPPFLAGS "$@" -fno-omit-frame-pointer else - set -- $PLATFORM $PREDEF $CCFLAGS $CFLAGS $CPPFLAGS $LDFLAGS $APEFLAGS $CFLAGS $CPPFLAGS "$@" \ - $LDLIBS -Wl,-z,common-page-size=4096 -Wl,-z,max-page-size=4096 $FRAME + set -- "$CC" $PLATFORM $PREDEF $CCFLAGS $CPPFLAGS $LDFLAGS $APEFLAGS $CPPFLAGS "$@" \ + $LDLIBS -Wl,-z,common-page-size=4096 -Wl,-z,max-page-size=4096 -fno-omit-frame-pointer fi -set -- "$CC" "$@" -printf '# %s\n(cd %s; %s)\n' "$ORIGINAL" "$PWD" "$*" >>/tmp/build.log +printf '# %s\n(cd %s; %s)\n' "$ORIGINAL" "$PWD" "$*" >>"${TMPDIR:-/tmp}/build.log" "$@" || exit if [ -n "$OUTPUT" ] && [ -f "$OUTPUT" ]; then if [ $INTENT = cc ] || [ $INTENT = ld ]; then - "$FIXUPOBJ" "$OUTPUT" || exit + "$COSMO/o/$MODE/tool/build/fixupobj.com" "$OUTPUT" || exit fi if [ $INTENT = ld ]; then if [ x"$OUTPUT" != x"${OUTPUT%.com}" ] || @@ -205,10 +250,10 @@ if [ -n "$OUTPUT" ] && [ -f "$OUTPUT" ]; then # -> foo.com (ape) # -> foo.com.dbg (elf) mv -f "$OUTPUT" "$OUTPUT.dbg" || exit - "$OBJCOPY" -S -O binary "$OUTPUT.dbg" "$OUTPUT" || exit - "$ZIPCOPY" "$OUTPUT.dbg" "$OUTPUT" || exit + "$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-objcopy" -S -O binary "$OUTPUT.dbg" "$OUTPUT" || exit + "$COSMO/o/$MODE/tool/build/zipcopy.com" "$OUTPUT.dbg" "$OUTPUT" || exit elif [ $SFLAG -eq 1 ]; then - "$STRIP" "$OUTPUT" || exit + "$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-strip" "$OUTPUT" || exit fi fi fi diff --git a/bin/fatcosmoc++ b/bin/fatcosmoc++ new file mode 120000 index 000000000..2c122c271 --- /dev/null +++ b/bin/fatcosmoc++ @@ -0,0 +1 @@ +fatcosmocc \ No newline at end of file diff --git a/bin/fatcosmocc b/bin/fatcosmocc new file mode 100755 index 000000000..346970fdc --- /dev/null +++ b/bin/fatcosmocc @@ -0,0 +1,310 @@ +#!/bin/sh +# +# fat cosmopolitan c compiler +# +# - this command is a drop-in replacement for the cc or gcc command. +# the difference is that (1) your binaries will be linked with the +# cosmopolitan c library, rather than your system specific tooling +# and (2) they'll be fat ape executables that run on the platforms +# +# * amd64 +# + linux +# + macos +# + windows +# + freebsd +# + openbsd +# + netbsd +# * arm64 +# + linux +# + macos +# + windows (non-native) +# +# - you need to use linux to build your binaries currently, but you +# can scp and distribute the output files to the above platforms! +# +# installation +# +# sudo chmod 1777 /opt +# git clone https://github.com/jart/cosmopolitan /opt/cosmo +# export PATH="$PATH:/opt/cosmo/bin:/opt/cosmos/bin" +# echo 'export PATH="$PATH:/opt/cosmo/bin:/opt/cosmos/bin"' >>~/.profile +# fatcosmocc --update # pull and rebuild toolchain artifacts +# +# getting started +# +# fatcosmocc -o hello.com hello.c +# ./foo.com +# ./foo.com.dbg +# +# building open source projects +# +# export CC=fatcosmocc +# export CXX=fatcosmoc++ +# ./configure --prefix=/opt/cosmos +# make -j +# make install +# +# cosmopolitan runtime flags +# +# ./hello.com --strace +# ./hello.com --ftrace +# +# cosmpolitan runtime libraries +# +# #include +# int main() { +# ShowCrashReports(); +# __builtin_trap(); +# } +# +# building in tiny mode +# +# export MODE=tiny +# fatcosmocc --update +# fatcosmocc -Os -o foo.com foo.c +# +# building in debug mode +# +# export MODE=dbg +# fatcosmocc --update +# fatcosmocc -g -o foo.com foo.c +# + +export PROG=${0##*/} +export COSMO=${COSMO:-/opt/cosmo} +export COSMOS=${COSMOS:-/opt/cosmos} +export ORIGINAL="$0 $*" + +if [ "$1" = "--version" ]; then +cat <&2 + exit 1 +fi + +if [ "$1" = "--update" ]; then + cd /opt/cosmo || exit + if GIT=$(command -v git); then + echo "$PROG: running git pull on cosmo..." >&2 + "$GIT" pull --quiet || exit + fi + echo "$PROG: building cosmo x86_64 toolchain..." >&2 + make --silent -j toolchain MODE="${MODE}" || exit + echo "$PROG: building cosmo aarch64 toolchain..." >&2 + make --silent -j toolchain MODE="${MODE_AARCH64}" || exit + "$COSMO/tool/scripts/setup-cosmos" + echo "$PROG: successfully updated your cosmo toolchain" >&2 + exit +fi + +if [ ! -d "$COSMO" ]; then + echo "$PROG: you need to clone cosmopolitan to your $COSMO directory" >&2 + exit 1 +fi + +if [ ! -d "$COSMOS" ] || + [ ! -x "$COSMO/o/$MODE/cosmopolitan.a" ] || + [ ! -x "$COSMO/o/$MODE_AARCH64/cosmopolitan.a" ]; then + echo "$PROG: you need to run: $PROG --update" >&2 + exit 1 +fi + +export FIXUPOBJ="$COSMO/o/$MODE/tool/build/fixupobj.com" + +OPT= +FIRST=1 +OUTPUT= +STRIP=0 +INTENT=ld +GOT_SOME=0 +SAVE_TEMPS=0 +NEED_OUTPUT= +FRAME="" +for x; do + if [ $FIRST -eq 1 ]; then + set -- + FIRST=0 + fi + if [ -n "$NEED_OUTPUT" ]; then + NEED_OUTPUT= + OUTPUT=$x + continue + fi + if [ x"$x" = x"${x#-*}" ]; then + GOT_SOME=1 + elif [ x"$x" = x"-o" ]; then + NEED_OUTPUT=1 + continue + elif [ x"$x" != x"${x#-o}" ]; then + OUTPUT=${x#-o} + continue + elif [ x"$x" != x"${x#-O}" ]; then + OPT=$x + elif [ x"$x" = x"-c" ]; then + INTENT=cc + elif [ x"$x" = x"-E" ]; then + INTENT=cpp + elif [ x"$x" = x"-s" ]; then + STRIP=1 + continue + elif [ x"$x" = x"-save-temps" ]; then + SAVE_TEMPS=1 + elif [ x"$x" = x"-fomit-frame-pointer" ]; then + # Quoth Apple "The frame pointer register must always address a + # valid frame record. Some functions — such as leaf functions or + # tail calls — may opt not to create an entry in this list. As a + # result, stack traces are always meaningful, even without debug + # information." + x="-momit-leaf-frame-pointer" + elif [ x"$x" = x"-r" ] || + [ x"$x" = x"-pie" ] || + [ x"$x" = x"-frtti" ] || + [ x"$x" = x"-shared" ] || + [ x"$x" = x"-nostdlib" ] || + [ x"$x" = x"-mred-zone" ] || + [ x"$x" = x"-fexceptions" ] || + [ x"$x" = x"-fsanitize=thread" ]; then + echo "$PROG: $x not supported" >&2 + exit 1 + elif [ x"$x" = x"-fsanitize=all" ] || + [ x"$x" = x"-fsanitize=address" ] || + [ x"$x" = x"-fsanitize=undefined" ]; then + echo "$PROG: use cosmo MODE=dbg rather than passing $x" >&2 + exit 1 + elif [ x"$x" = x"-mno-red-zone" ]; then + # "Any memory below the stack beyond the red zone is considered + # volatile and may be modified by the operating system at any time." + # https://devblogs.microsoft.com/oldnewthing/20190111-00/?p=100685 + continue + elif [ x"$x" = x"-fpic" ] || [ x"$x" = x"-fPIC" ]; then + # no support for building dynamic shared objects yet. reports + # indicate that ignoring these flags, helps let autoconf know + continue + elif [ x"$x" = x"-Werror" ] || \ + [ x"$x" = x"-pedantic-errors" ]; then + # this toolchain is intended for building other people's code + # elevating warnings into errors, should only be done by devs + continue + elif [ x"$x" = x"-static-libgcc" ] || \ + [ x"$x" = x"-shared-libgcc" ]; then + # cosmopolitan.a always has llvm compiler runtime static code + continue + fi + set -- "$@" "$x" +done + +if [ x"$MODE" = x"dbg" ]; then + set -- \ + -fsanitize=address \ + -fsanitize=undefined \ + "$@" +fi + +if [ x"$OPT" != x"-Os" ] && + [ x"${MODE#tiny}" != x"${MODE}" ]; then + set -- \ + -fno-optimize-sibling-calls \ + -mno-omit-leaf-frame-pointer \ + "$@" +fi + +set -- \ + -fno-pie \ + -fportcosmo \ + -fno-dwarf2-cfi-asm \ + -fno-unwind-tables \ + -fno-asynchronous-unwind-tables \ + -fno-semantic-interposition \ + -fno-math-errno \ + "$@" \ + -fno-omit-frame-pointer + +PLATFORM="-D__COSMOPOLITAN__" +PREDEF="-include libc/integral/normalize.inc" +CPPFLAGS="-nostdinc -iquote $COSMO -isystem $COSMOS/include -isystem $COSMO/libc/isystem" + +if [ "$GOT_SOME" -eq 0 ]; then + echo "$PROG: fatal error: no input files" >&2 + echo "compilation terminated." >&2 + exit 1 +fi + +if [ $INTENT = cpp ]; then + if [ -n "$OUTPUT" ]; then + set -- "$@" -o"$OUTPUT" + fi + MODE="$MODE" "$COSMO/tool/scripts/fat-x86_64" \ + -U__x86_64__ $PLATFORM $CPPFLAGS "$@" + exit +fi + +if [ -z "$OUTPUT" ]; then + if [ $INTENT = cc ]; then + echo "$PROG: passing -c without -o flag not supported" >&2 + exit 1 + fi + OUTPUT=a.out +fi + +set -- $PLATFORM $PREDEF $CPPFLAGS "$@" + +out2=$(mktemp "${TMPDIR:-/tmp}/ccc.XXXXXX") || exit + +MODE="$MODE" \ +"$COSMO/tool/scripts/fat-x86_64" -o"$OUTPUT.x86_64" "$@" & +pid1=$! + +MODE="$MODE_AARCH64" \ +"$COSMO/tool/scripts/fat-aarch64" -o"$OUTPUT.aarch64" "$@" 2>"$out2" & +pid2=$! + +if ! wait $pid1; then + wait + rm -f "$out2" + exit 1 +fi + +if ! wait $pid2; then + wait + echo "$PROG: aarch64 compiler failed with:" >&2 + cat "$out2" >&2 + rm -f "$out2" + exit 1 +fi + +rm -f "$out2" + +set -- \ +"$COSMO/o/$MODE/tool/build/apelink.com" \ + -l "$COSMO/o/$MODE/ape/ape.elf" \ + -l "$COSMO/o/$MODE_AARCH64/ape/ape.elf" \ + -M "$COSMO/ape/ape-m1.c" \ + -o "$OUTPUT" \ + "$OUTPUT.x86_64" \ + "$OUTPUT.aarch64" +printf '# %s\n(cd %s; %s)\n' "$ORIGINAL" "$PWD" "$*" >>"${TMPDIR:-/tmp}/build.log" +"$@" || exit + +"$COSMO/o/$MODE/tool/build/pecheck.com" "$OUTPUT" || exit + +if [ $SAVE_TEMPS -eq 0 ]; then + rm -f "$OUTPUT.x86_64" \ + "$OUTPUT.aarch64" +fi diff --git a/bin/unknown-unknown-cosmo-ar b/bin/unknown-unknown-cosmo-ar new file mode 100755 index 000000000..1a2485251 --- /dev/null +++ b/bin/unknown-unknown-cosmo-ar @@ -0,0 +1 @@ +#!/bin/sh diff --git a/bin/unknown-unknown-cosmo-c++ b/bin/unknown-unknown-cosmo-c++ new file mode 120000 index 000000000..2c122c271 --- /dev/null +++ b/bin/unknown-unknown-cosmo-c++ @@ -0,0 +1 @@ +fatcosmocc \ No newline at end of file diff --git a/bin/unknown-unknown-cosmo-cc b/bin/unknown-unknown-cosmo-cc new file mode 120000 index 000000000..2c122c271 --- /dev/null +++ b/bin/unknown-unknown-cosmo-cc @@ -0,0 +1 @@ +fatcosmocc \ No newline at end of file diff --git a/bin/unknown-unknown-cosmo-g++ b/bin/unknown-unknown-cosmo-g++ new file mode 120000 index 000000000..2c122c271 --- /dev/null +++ b/bin/unknown-unknown-cosmo-g++ @@ -0,0 +1 @@ +fatcosmocc \ No newline at end of file diff --git a/bin/unknown-unknown-cosmo-gcc b/bin/unknown-unknown-cosmo-gcc new file mode 120000 index 000000000..2c122c271 --- /dev/null +++ b/bin/unknown-unknown-cosmo-gcc @@ -0,0 +1 @@ +fatcosmocc \ No newline at end of file diff --git a/bin/x86_64-unknown-cosmo-addr2line b/bin/x86_64-unknown-cosmo-addr2line new file mode 100755 index 000000000..5f7287848 --- /dev/null +++ b/bin/x86_64-unknown-cosmo-addr2line @@ -0,0 +1,13 @@ +#!/bin/sh + +MODE=${MODE:-$m} +COSMO=${COSMO:-/opt/cosmo} +COSMOS=${COSMOS:-/opt/cosmos} +TOOL="$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-addr2line" + +if [ ! -x "$TOOL" ]; then + echo "$0: you need to run: cosmocc --update" >&2 + exit 1 +fi + +exec "$TOOL" "$@" diff --git a/bin/x86_64-unknown-cosmo-ar b/bin/x86_64-unknown-cosmo-ar new file mode 100755 index 000000000..a5c44ed65 --- /dev/null +++ b/bin/x86_64-unknown-cosmo-ar @@ -0,0 +1,18 @@ +#!/bin/sh + +MODE=${MODE:-$m} +COSMO=${COSMO:-/opt/cosmo} +COSMOS=${COSMOS:-/opt/cosmos} + +if [ x"$1" = x"rcs" ] || [ x"$1" = x"rcsD" ]; then + TOOL="$COSMO/o/$MODE/tool/build/ar.com" +else + TOOL="$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-ar" +fi + +if [ ! -x "$TOOL" ]; then + echo "$0: you need to run: cosmocc --update" >&2 + exit 1 +fi + +exec "$TOOL" "$@" diff --git a/bin/x86_64-unknown-cosmo-as b/bin/x86_64-unknown-cosmo-as new file mode 100755 index 000000000..50c484ead --- /dev/null +++ b/bin/x86_64-unknown-cosmo-as @@ -0,0 +1,13 @@ +#!/bin/sh + +MODE=${MODE:-$m} +COSMO=${COSMO:-/opt/cosmo} +COSMOS=${COSMOS:-/opt/cosmos} +TOOL="$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-as" + +if [ ! -x "$TOOL" ]; then + echo "$0: you need to run: cosmocc --update" >&2 + exit 1 +fi + +exec "$TOOL" "$@" diff --git a/bin/x86_64-unknown-cosmo-c++ b/bin/x86_64-unknown-cosmo-c++ new file mode 120000 index 000000000..978d77998 --- /dev/null +++ b/bin/x86_64-unknown-cosmo-c++ @@ -0,0 +1 @@ +cosmocc \ No newline at end of file diff --git a/bin/x86_64-unknown-cosmo-cc b/bin/x86_64-unknown-cosmo-cc new file mode 120000 index 000000000..978d77998 --- /dev/null +++ b/bin/x86_64-unknown-cosmo-cc @@ -0,0 +1 @@ +cosmocc \ No newline at end of file diff --git a/bin/x86_64-unknown-cosmo-g++ b/bin/x86_64-unknown-cosmo-g++ new file mode 120000 index 000000000..978d77998 --- /dev/null +++ b/bin/x86_64-unknown-cosmo-g++ @@ -0,0 +1 @@ +cosmocc \ No newline at end of file diff --git a/bin/x86_64-unknown-cosmo-gcc b/bin/x86_64-unknown-cosmo-gcc new file mode 120000 index 000000000..978d77998 --- /dev/null +++ b/bin/x86_64-unknown-cosmo-gcc @@ -0,0 +1 @@ +cosmocc \ No newline at end of file diff --git a/bin/x86_64-unknown-cosmo-ld b/bin/x86_64-unknown-cosmo-ld new file mode 100755 index 000000000..54b612f21 --- /dev/null +++ b/bin/x86_64-unknown-cosmo-ld @@ -0,0 +1,13 @@ +#!/bin/sh + +MODE=${MODE:-$m} +COSMO=${COSMO:-/opt/cosmo} +COSMOS=${COSMOS:-/opt/cosmos} +TOOL="$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-ld" + +if [ ! -x "$TOOL" ]; then + echo "$0: you need to run: cosmocc --update" >&2 + exit 1 +fi + +exec "$TOOL" "$@" diff --git a/bin/x86_64-unknown-cosmo-objcopy b/bin/x86_64-unknown-cosmo-objcopy new file mode 100755 index 000000000..dff5c68ee --- /dev/null +++ b/bin/x86_64-unknown-cosmo-objcopy @@ -0,0 +1,13 @@ +#!/bin/sh + +MODE=${MODE:-$m} +COSMO=${COSMO:-/opt/cosmo} +COSMOS=${COSMOS:-/opt/cosmos} +TOOL="$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-objcopy" + +if [ ! -x "$TOOL" ]; then + echo "$0: you need to run: cosmocc --update" >&2 + exit 1 +fi + +exec "$TOOL" "$@" diff --git a/bin/x86_64-unknown-cosmo-strip b/bin/x86_64-unknown-cosmo-strip new file mode 100755 index 000000000..be368592c --- /dev/null +++ b/bin/x86_64-unknown-cosmo-strip @@ -0,0 +1,13 @@ +#!/bin/sh + +MODE=${MODE:-$m} +COSMO=${COSMO:-/opt/cosmo} +COSMOS=${COSMOS:-/opt/cosmos} +TOOL="$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-strip" + +if [ ! -x "$TOOL" ]; then + echo "$0: you need to run: cosmocc --update" >&2 + exit 1 +fi + +exec "$TOOL" "$@" diff --git a/build/definitions.mk b/build/definitions.mk index 077fbacf4..1306edcf2 100644 --- a/build/definitions.mk +++ b/build/definitions.mk @@ -83,7 +83,6 @@ COMPILE = build/bootstrap/compile.com -V9 -P4096 $(QUOTA) COMMA := , PWD := $(shell build/bootstrap/pwd.com) -IGNORE := $(shell $(ECHO) -2 ♥cosmo) IGNORE := $(shell $(MKDIR) $(TMPDIR)) ifneq ($(findstring aarch64,$(MODE)),) @@ -188,6 +187,10 @@ DEFAULT_COPTS ?= \ -fno-asynchronous-unwind-tables ifeq ($(ARCH), x86_64) +# Microsoft says "[a]ny memory below the stack beyond the red zone +# [note: Windows defines the x64 red zone size as 0] is considered +# volatile and may be modified by the operating system at any time." +# https://devblogs.microsoft.com/oldnewthing/20190111-00/?p=100685 DEFAULT_COPTS += \ -mno-red-zone \ -mno-tls-direct-seg-refs @@ -201,6 +204,9 @@ ifeq ($(ARCH), aarch64) # - Cosmopolitan Libc uses x28 for thread-local storage because Apple # forbids us from using tpidr_el0 too. # +# - Cosmopolitan currently lacks an implementation of the runtime +# libraries needed by the -moutline-atomics flag +# DEFAULT_COPTS += \ -ffixed-x18 \ -ffixed-x28 \ diff --git a/libc/stdio/putwc_unlocked.c b/libc/stdio/putwc_unlocked.c index 361a0cca6..1c7255bc2 100644 --- a/libc/stdio/putwc_unlocked.c +++ b/libc/stdio/putwc_unlocked.c @@ -23,6 +23,6 @@ * * @return wc if written or -1 w/ errno */ -wint_t(putwc_unlocked)(wchar_t wc, FILE *f) { +wint_t putwc_unlocked(wchar_t wc, FILE *f) { return fputwc_unlocked(wc, f); } diff --git a/libc/stdio/rand.h b/libc/stdio/rand.h index 37c42dc97..d8df755c9 100644 --- a/libc/stdio/rand.h +++ b/libc/stdio/rand.h @@ -9,11 +9,6 @@ COSMOPOLITAN_C_START_ int rand(void); void srand(unsigned); -double poz(double); -double pochisq(double, int); -void rt_init(int); -void rt_add(void *, int); -void rt_end(double *, double *, double *, double *, double *); char *strfry(char *); int getentropy(void *, size_t); ssize_t getrandom(void *, size_t, unsigned); @@ -28,6 +23,8 @@ void srandom(unsigned); #define rngset __rngset #define rdrand __rdrand #define rdseed __rdseed +double poz(double); +double pochisq(double, int); uint64_t lemur64(void); uint64_t _rand64(void); uint64_t vigna(void); @@ -43,6 +40,9 @@ double _real2(uint64_t); double _real3(uint64_t); double MeasureEntropy(const char *, size_t); void *rngset(void *, size_t, uint64_t (*)(void), size_t); +void rt_init(int); +void rt_add(void *, int); +void rt_end(double *, double *, double *, double *, double *); #endif /* COSMO */ COSMOPOLITAN_C_END_ diff --git a/tool/build/apelink.c b/tool/build/apelink.c index 54f646d6b..a9a7e56f5 100644 --- a/tool/build/apelink.c +++ b/tool/build/apelink.c @@ -77,6 +77,8 @@ "\n" \ " -o OUTPUT set output path\n" \ "\n" \ + " -s never embed symbol table\n" \ + "\n" \ " -l PATH bundle ape loader executable [repeatable]\n" \ " if no ape loaders are specified then your\n" \ " executable will self-modify its header on\n" \ @@ -86,7 +88,7 @@ " processors running the xnu kernel so that\n" \ " it can be compiled on the fly by xcode\n" \ "\n" \ - " -s BITS set OS support vector\n" \ + " -V BITS set OS support vector\n" \ "\n" \ " the default value is -1 which sets the bits\n" \ " for all supported operating systems to true\n" \ @@ -232,6 +234,7 @@ struct Assets { static int outfd; static int hashes; static const char *prog; +static bool want_stripped; static int support_vector; static int macholoadcount; static const char *outpath; @@ -246,6 +249,7 @@ static bool dont_path_lookup_ape_loader; _Alignas(4096) static char prologue[1048576]; static uint8_t hashpool[BLAKE2B256_DIGEST_LENGTH]; static const char *macos_silicon_loader_source_path; +static const char *macos_silicon_loader_source_text; static char *macos_silicon_loader_source_ddarg_skip; static char *macos_silicon_loader_source_ddarg_size; @@ -329,6 +333,16 @@ static const char *DescribePhdrType(Elf64_Word p_type) { } } +static bool IsBinary(const char *p, size_t n) { + size_t i; + for (i = 0; i < n; ++i) { + if ((p[i] & 255) < '\t') { + return true; + } + } + return false; +} + static void BlendHashes(uint8_t out[static BLAKE2B256_DIGEST_LENGTH], uint8_t inp[static BLAKE2B256_DIGEST_LENGTH]) { int i; @@ -349,6 +363,28 @@ static void HashInputString(const char *str) { HashInput(str, strlen(str)); } +static char *LoadSourceCode(const char *path) { + int fd; + size_t i; + char *text; + ssize_t rc, size; + if ((fd = open(path, O_RDONLY)) == -1) DieSys(path); + if ((size = lseek(fd, 0, SEEK_END)) == -1) DieSys(path); + text = Malloc(size + 1); + text[size] = 0; + for (i = 0; i < size; i += rc) { + if ((rc = pread(fd, text, size - i, i)) <= 0) { + DieSys(path); + } + if (IsBinary(text, rc)) { + Die(path, "source code contains binary data"); + } + } + if (close(fd)) DieSys(path); + HashInput(text, size); + return text; +} + static void Pwrite(const void *data, size_t size, uint64_t offset) { ssize_t rc; const char *p, *e; @@ -928,13 +964,17 @@ static void GetOpts(int argc, char *argv[]) { char *endptr; int opt, bits; bool got_support_vector = false; - while ((opt = getopt(argc, argv, "hvgGBo:s:l:S:M:")) != -1) { + while ((opt = getopt(argc, argv, "hvgsGBo:l:S:M:V:")) != -1) { switch (opt) { case 'o': outpath = optarg; break; case 's': HashInputString("-s"); + want_stripped = true; + break; + case 'V': + HashInputString("-V"); HashInputString(optarg); if (ParseSupportVector(optarg, &bits)) { support_vector |= bits; @@ -945,22 +985,30 @@ static void GetOpts(int argc, char *argv[]) { got_support_vector = true; break; case 'l': + HashInputString("-l"); AddLoader(optarg); break; case 'S': + HashInputString("-S"); + HashInputString(optarg); custom_sh_code = optarg; break; case 'B': + HashInputString("-B"); force_bypass_binfmt_misc = true; break; case 'g': + HashInputString("-g"); generate_debuggable_binary = true; break; case 'G': + HashInputString("-G"); dont_path_lookup_ape_loader = true; break; case 'M': + HashInputString("-M"); macos_silicon_loader_source_path = optarg; + macos_silicon_loader_source_text = LoadSourceCode(optarg); break; case 'v': tinyprint(0, VERSION, NULL); @@ -1740,7 +1788,7 @@ static void CopyZips(Elf64_Off offset) { int main(int argc, char *argv[]) { char *p; - int i, opt; + int i, j, opt; Elf64_Off offset; char empty[64] = {0}; Elf64_Xword prologue_bytes; @@ -1776,11 +1824,26 @@ int main(int argc, char *argv[]) { for (i = 0; i < loaders.n; ++i) { OpenLoader(loaders.p + i); } + for (i = 0; i < loaders.n; ++i) { + for (j = i + 1; j < loaders.n; ++j) { + if (loaders.p[i].os == loaders.p[j].os && + loaders.p[i].machine == loaders.p[j].machine) { + Die(prog, "multiple ape loaders specified for the same platform"); + } + } + } // open input files for (i = optind; i < argc; ++i) { OpenInput(argv[i]); } + for (i = 0; i < inputs.n; ++i) { + for (j = i + 1; j < inputs.n; ++j) { + if (inputs.p[i].elf->e_machine == inputs.p[j].elf->e_machine) { + Die(prog, "multiple executables passed for the same machine type"); + } + } + } // validate input files for (i = 0; i < inputs.n; ++i) { @@ -1789,15 +1852,17 @@ int main(int argc, char *argv[]) { } // load symbols - for (i = 0; i < inputs.n; ++i) { - struct Input *in = inputs.p + i; - if (GetElfSymbol(in, "__zipos_get")) { - LoadSymbols(in->elf, in->size, in->path); - } else { - tinyprint(2, in->path, - ": warning: won't generate symbol table unless " - "__static_yoink(\"zipos\") is linked\n", - NULL); + if (!want_stripped) { + for (i = 0; i < inputs.n; ++i) { + struct Input *in = inputs.p + i; + if (GetElfSymbol(in, "__zipos_get")) { + LoadSymbols(in->elf, in->size, in->path); + } else { + tinyprint(2, in->path, + ": warning: won't generate symbol table unless " + "__static_yoink(\"zipos\") is linked\n", + NULL); + } } } @@ -2046,11 +2111,7 @@ int main(int argc, char *argv[]) { } p = stpcpy(p, "fi\n"); // if [ -d /Applications ]; then } else { - if (macos_silicon_loader_source_path) { - Die(macos_silicon_loader_source_path, - "won't embed macos arm64 ape loader source code because xnu isn't " - "in the support vector"); - } + macos_silicon_loader_source_path = 0; } // extract the ape loader for open platforms @@ -2131,25 +2192,16 @@ int main(int argc, char *argv[]) { // concatenate ape loader source code if (macos_silicon_loader_source_path) { - int fd; - char *map; - ssize_t size; char *compressed_data; size_t compressed_size; - fd = open(macos_silicon_loader_source_path, O_RDONLY); - if (fd == -1) DieSys(macos_silicon_loader_source_path); - size = lseek(fd, 0, SEEK_END); - if (size == -1) DieSys(macos_silicon_loader_source_path); - map = mmap(0, size, PROT_READ, MAP_PRIVATE, fd, 0); - if (map == MAP_FAILED) DieSys(macos_silicon_loader_source_path); - compressed_data = Gzip(map, size, &compressed_size); + compressed_data = + Gzip(macos_silicon_loader_source_text, + strlen(macos_silicon_loader_source_text), &compressed_size); FixupWordAsDecimal(macos_silicon_loader_source_ddarg_skip, offset); FixupWordAsDecimal(macos_silicon_loader_source_ddarg_size, compressed_size); Pwrite(compressed_data, compressed_size, offset); offset += compressed_size; free(compressed_data); - munmap(map, size); - close(fd); } // add the zip files diff --git a/tool/build/march-native.c b/tool/build/march-native.c new file mode 100644 index 000000000..36fc3f5c9 --- /dev/null +++ b/tool/build/march-native.c @@ -0,0 +1,184 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2023 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/calls.h" +#include "libc/nexgen32e/x86feature.h" +#include "libc/nexgen32e/x86info.h" +#include "libc/runtime/runtime.h" +#include "third_party/getopt/getopt.internal.h" + +/** + * @fileoverview Command for printing `-march=native` flags. + * + * In recent years (2023) compilers have decided to remove support for + * the `-march=native` flag, even on x86. That's unfortunate, since as + * we can see below, grokking all the various microarchitecture is not + * something a compiler should reasonably expect from users especially + * not for a flag as important as this one, which can have a night and + * day impact for apps that do scientific computing. + * + * This is a tiny program, that makes it easy for shell scripts to get + * these flags. + */ + +#define VERSION \ + "-march=native flag printer v0.1\n" \ + "copyright 2023 justine alexandra roberts tunney\n" + +#define USAGE \ + "usage: march-native.com [-hvc]\n" \ + " -h show help\n" \ + " -v show version\n" \ + " -c assume we're using clang (not gcc)\n" + +static bool isclang; + +static void GetOpts(int argc, char *argv[]) { + int opt; + while ((opt = getopt(argc, argv, "hvc")) != -1) { + switch (opt) { + case 'c': + isclang = true; + break; + case 'v': + tinyprint(1, VERSION, NULL); + exit(0); + case 'h': + tinyprint(1, VERSION, USAGE, NULL); + exit(0); + default: + tinyprint(2, VERSION, USAGE, NULL); + exit(1); + } + } +} + +static void Puts(const char *s) { + tinyprint(1, s, "\n", NULL); +} + +int main(int argc, char *argv[]) { + GetOpts(argc, argv); +#ifdef __x86_64__ + struct X86ProcessorModel *model; + if (X86_HAVE(XOP)) Puts("-mxop"); + if (X86_HAVE(SSE4A)) Puts("-msse4a"); + if (X86_HAVE(SSE3)) Puts("-msse3"); + if (X86_HAVE(SSSE3)) Puts("-mssse3"); + if (X86_HAVE(SSE4_1)) Puts("-msse4.1"); + if (X86_HAVE(SSE4_2)) Puts("-msse4.2"); + if (X86_HAVE(AVX)) Puts("-mavx"); + if (X86_HAVE(AVX2)) { + Puts("-mavx2"); + if (!isclang) { + Puts("-msse2avx"); + Puts("-Wa,-msse2avx"); + } + } + if (X86_HAVE(AVX512F)) Puts("-mavx512f"); + if (X86_HAVE(AVX512PF)) Puts("-mavx512pf"); + if (X86_HAVE(AVX512ER)) Puts("-mavx512er"); + if (X86_HAVE(AVX512CD)) Puts("-mavx512cd"); + if (X86_HAVE(AVX512VL)) Puts("-mavx512vl"); + if (X86_HAVE(AVX512BW)) Puts("-mavx512bw"); + if (X86_HAVE(AVX512DQ)) Puts("-mavx512dq"); + if (X86_HAVE(AVX512IFMA)) Puts("-mavx512ifma"); + if (X86_HAVE(AVX512VBMI)) Puts("-mavx512vbmi"); + if (X86_HAVE(SHA)) Puts("-msha"); + if (X86_HAVE(AES)) Puts("-maes"); + if (X86_HAVE(VAES)) Puts("-mvaes"); + if (X86_HAVE(PCLMUL)) Puts("-mpclmul"); + if (X86_HAVE(FSGSBASE)) Puts("-mfsgsbase"); + if (X86_HAVE(F16C)) Puts("-mf16c"); + if (X86_HAVE(FMA)) Puts("-mfma"); + if (X86_HAVE(POPCNT)) Puts("-mpopcnt"); + if (X86_HAVE(BMI)) Puts("-mbmi"); + if (X86_HAVE(BMI2)) Puts("-mbmi2"); + if (X86_HAVE(ADX)) Puts("-madx"); + if (X86_HAVE(FXSR)) Puts("-mfxsr"); + if ((model = getx86processormodel(kX86ProcessorModelKey))) { + switch (model->march) { + case X86_MARCH_CORE2: + Puts("-march=core2"); + break; + case X86_MARCH_NEHALEM: + Puts("-march=nehalem"); + break; + case X86_MARCH_WESTMERE: + Puts("-march=westmere"); + break; + case X86_MARCH_SANDYBRIDGE: + Puts("-march=sandybridge"); + break; + case X86_MARCH_IVYBRIDGE: + Puts("-march=ivybridge"); + break; + case X86_MARCH_HASWELL: + Puts("-march=haswell"); + break; + case X86_MARCH_BROADWELL: + Puts("-march=broadwell"); + break; + case X86_MARCH_SKYLAKE: + case X86_MARCH_KABYLAKE: + Puts("-march=skylake"); + break; + case X86_MARCH_CANNONLAKE: + Puts("-march=cannonlake"); + break; + case X86_MARCH_ICELAKE: + if (model->grade >= X86_GRADE_SERVER) { + Puts("-march=icelake-server"); + } else { + Puts("-march=icelake-client"); + } + break; + case X86_MARCH_TIGERLAKE: + Puts("-march=tigerlake"); + break; + case X86_MARCH_BONNELL: + case X86_MARCH_SALTWELL: + Puts("-march=bonnell"); + break; + case X86_MARCH_SILVERMONT: + case X86_MARCH_AIRMONT: + Puts("-march=silvermont"); + break; + case X86_MARCH_GOLDMONT: + Puts("-march=goldmont"); + break; + case X86_MARCH_GOLDMONTPLUS: + Puts("-march=goldmont-plus"); + break; + case X86_MARCH_TREMONT: + Puts("-march=tremont"); + break; + case X86_MARCH_KNIGHTSLANDING: + Puts("-march=knl"); + break; + case X86_MARCH_KNIGHTSMILL: + Puts("-march=knm"); + break; + } + } +#elif defined(__aarch64__) + // TODO(jart): How can we determine CPU features on AARCH64? +#else + // otherwise do nothing (it's usually best) +#endif +} diff --git a/tool/hello/hello.mk b/tool/hello/hello.mk index a06acf14d..2a192cebc 100644 --- a/tool/hello/hello.mk +++ b/tool/hello/hello.mk @@ -54,7 +54,7 @@ o/$(MODE)/tool/hello/hello-elf.com: \ o/$(MODE)/tool/hello/hello.com.dbg \ o/$(MODE)/tool/build/apelink.com \ o/$(MODE)/ape/ape.elf - @$(COMPILE) -ALINK.ape o/$(MODE)/tool/build/apelink.com -s elf -o $@ -l o/$(MODE)/ape/ape.elf $< + @$(COMPILE) -ALINK.ape o/$(MODE)/tool/build/apelink.com -V elf -o $@ -l o/$(MODE)/ape/ape.elf $< # uses apelink to generate non-pe ape executable # support vector = macos/linux/freebsd/openbsd/netbsd @@ -64,7 +64,7 @@ o/$(MODE)/tool/hello/hello-unix.com: \ o/$(MODE)/tool/hello/hello.com.dbg \ o/$(MODE)/tool/build/apelink.com \ o/$(MODE)/ape/ape.elf - @$(COMPILE) -ALINK.ape o/$(MODE)/tool/build/apelink.com -s unix -o $@ -l o/$(MODE)/ape/ape.elf $< + @$(COMPILE) -ALINK.ape o/$(MODE)/tool/build/apelink.com -V unix -o $@ -l o/$(MODE)/ape/ape.elf $< # elf2pe generates optimal pe binaries # windows is the only platform supported diff --git a/tool/scripts/cosmoc++ b/tool/scripts/cosmoc++ deleted file mode 100755 index 8de17d06a..000000000 --- a/tool/scripts/cosmoc++ +++ /dev/null @@ -1,216 +0,0 @@ -#!/bin/sh -# -# cosmopolitan c++ compiler -# -# getting started -# -# sudo chmod 1777 /opt -# git clone https://github.com/jart/cosmopolitan /opt/cosmo -# (cd /opt/cosmo; make -j8 toolchain) -# sudo ln -sf /opt/cosmo/tool/scripts/cosmocc /usr/local/bin/cosmocc -# sudo ln -sf /opt/cosmo/tool/scripts/cosmoc++ /usr/local/bin/cosmoc++ -# cosmoc++ -o hello.com hello.cc -# ./foo.com -# ./foo.com.dbg -# -# building open source projects -# -# export CC=cosmocc -# export CXX=cosmoc++ -# ./configure --prefix=/opt/cosmos -# make -j -# make install -# -# cosmopolitan runtime flags -# -# ./hello.com --strace -# ./hello.com --ftrace -# -# cosmpolitan runtime libraries -# -# #include -# int main() { -# ShowCrashReports(); -# __builtin_trap(); -# } -# -# building in tiny mode -# -# export MODE=tiny -# (cd /opt/cosmo; make -j8 toolchain) -# cosmoc++ -Os -o foo.com foo.cc -# -# building in tiniest mode (linux only) -# -# export MODE=tinylinux -# (cd /opt/cosmo; make -j8 toolchain) -# cosmoc++ -Os -o foo.com foo.c -# -# hardening programs with memory safety -# -# export MODE=asan -# (cd /opt/cosmo; make -j8 toolchain) -# cosmoc++ -o foo.com foo.cc -# - -MODE=${MODE:-$m} -COSMO=${COSMO:-/opt/cosmo} -COSMOS=${COSMOS:-/opt/cosmos} - -if [ "$1" = "--version" ]; then -cat <<'EOF' -x86_64-unknown-cosmo-g++ (GCC) 11.2.0 -Copyright (C) 2019 Free Software Foundation, Inc. -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -EOF -exit 0 -fi - -ORIGINAL="$0 $*" -PLATFORM="-D__COSMOPOLITAN__" -PREDEF="-include libc/integral/normalize.inc" -CCFLAGS="-fdata-sections -ffunction-sections -fno-pie -mno-tls-direct-seg-refs -mno-red-zone -fportcosmo" -CXXFLAGS="-fno-rtti -fno-exceptions -fuse-cxa-atexit -fno-threadsafe-statics" -CPPFLAGS="-nostdinc -iquote $COSMO -isystem $COSMOS/include -isystem $COSMO/libc/isystem" -LDFLAGS="-static -no-pie -nostdlib -fuse-ld=bfd -Wl,-melf_x86_64" -APEFLAGS="-L$COSMOS/lib -Wl,--gc-sections -Wl,-T,$COSMO/o/$MODE/ape/public/ape.lds $COSMO/o/$MODE/ape/ape-no-modify-self.o $COSMO/o/$MODE/libc/crt/crt.o" -LDLIBS="$COSMO/o/$MODE/third_party/libcxx/libcxx.a $COSMO/o/$MODE/cosmopolitan.a" - -CXX="$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-g++" -STRIP="$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-strip" -OBJCOPY="$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-objcopy" -FIXUPOBJ="$COSMO/o/$MODE/tool/build/fixupobj.com" -ZIPCOPY="$COSMO/o/$MODE/tool/build/zipcopy.com" - -if [ ! -d "$COSMO" ]; then - echo "you need to checkout cosmopolitan to your $COSMO directory" >&2 - exit 1 -fi - -if [ ! -d "$COSMOS" ]; then - echo "you need to create your $COSMOS directory" >&2 - exit 1 -fi - -if [ ! -f "$CXX" ] || - [ ! -f "$OBJCOPY" ] || - [ ! -f "$FIXUPOBJ" ] || - [ ! -f "$ZIPCOPY" ]; then - echo "error: cosmopolitan artifacts missing; please run" >&2 - echo " cd $COSMOS" >&2 - echo " make -j8 m=$MODE toolchain" >&2 - exit 1 -fi - -# auto-install some shell libraries -if [ ! -d "$COSMOS/lib" ]; then - mkdir -p "$COSMOS/lib" -fi -for lib in c dl gcc_s m pthread resolv rt dl z stdc++; do - if [ ! -f "$COSMOS/lib/lib$lib.a" ]; then - printf '\041\074\141\162\143\150\076\012' >"$COSMOS/lib/lib$lib.a" - fi -done - -OPT= -FIRST=1 -OUTPUT= -SFLAG=0 -INTENT=ld -NEED_OUTPUT= -RELOCATABLE=0 -FRAME=-fno-omit-frame-pointer -for x; do - if [ $FIRST -eq 1 ]; then - set -- - FIRST=0 - fi - if [ x"$x" = x"-Werror" ]; then - # this toolchain is intended for building other people's code - # elevating warnings into errors, should only be done by devs - continue - elif [ x"$x" = x"-pedantic" ]; then - # this toolchain is intended for building other people's code - # we don't need the compiler's assistance to be more portable - continue - elif [ x"$x" = x"-static-libstdc++" ]; then - continue - elif [ x"$x" = x"-static-libgcc" ]; then - continue - elif [ x"$x" != x"${x#-O}" ]; then - OPT=$x - elif [ x"$x" = x"-c" ]; then - INTENT=cc - elif [ x"$x" = x"-s" ]; then - SFLAG=1 - continue - elif [ x"$x" = x"-r" ]; then - RELOCATABLE=1 - elif [ x"$x" = x"-E" ]; then - INTENT=cpp - elif [ x"$x" = x"-o" ]; then - NEED_OUTPUT=1 - elif [ x"$x" != x"${x#-o}" ]; then - OUTPUT=${x#-o} - elif [ -n "$NEED_OUTPUT" ]; then - NEED_OUTPUT= - OUTPUT=$x - elif [ x"$x" = x"-fpic" ]; then - continue - elif [ x"$x" = x"-fPIC" ]; then - continue - elif [ x"$x" = x"-shared" ]; then - echo "error: cosmocc -shared isn't supported" >&2 - exit 1 - elif [ x"$x" = x"-fomit-frame-pointer" ] || [ x"$x" = x"-fno-omit-frame-pointer" ]; then - FRAME=$x - continue - fi - set -- "$@" "$x" -done - -if [ $RELOCATABLE -eq 1 ]; then - APEFLAGS="-r" -fi - -if [ x"$MODE" = x"nox87" ]; then - CCFLAGS="$CCFLAGS -mlong-double-64" -fi - -if [ x"$OPT" != x"-Os" ] && [ x"${MODE#tiny}" != x"${MODE}" ]; then - # support --ftrace unless optimizing for size - CXXFLAGS="$CXXFLAGS -fpatchable-function-entry=18,16" -fi - -if [ $INTENT = cpp ]; then - set -- $PLATFORM $CCFLAGS $CPPFLAGS "$@" -elif [ $INTENT = cc ]; then - set -- $PLATFORM $PREDEF $CCFLAGS $CXXFLAGS $CPPFLAGS "$@" $FRAME -else - set -- $PLATFORM $PREDEF $CCFLAGS $CXXFLAGS $CPPFLAGS $LDFLAGS $APEFLAGS $CXXFLAGS $CPPFLAGS "$@" \ - $LDLIBS -Wl,-z,common-page-size=4096 -Wl,-z,max-page-size=4096 $FRAME -fi - -set -- "$CXX" "$@" -printf '# %s\n(cd %s; %s)\n' "$ORIGINAL" "$PWD" "$*" >>/tmp/build.log -"$@" || exit - -if [ -n "$OUTPUT" ] && [ -f "$OUTPUT" ]; then - if [ $INTENT = cc ] || [ $INTENT = ld ]; then - "$FIXUPOBJ" "$OUTPUT" || exit - fi - if [ $INTENT = ld ]; then - if [ x"$OUTPUT" != x"${OUTPUT%.com}" ] || - [ x"$OUTPUT" != x"${OUTPUT%.exe}" ]; then - # cosmocc -o foo.com ... - # -> foo.com (ape) - # -> foo.com.dbg (elf) - mv -f "$OUTPUT" "$OUTPUT.dbg" || exit - "$OBJCOPY" -S -O binary "$OUTPUT.dbg" "$OUTPUT" || exit - "$ZIPCOPY" "$OUTPUT.dbg" "$OUTPUT" || exit - elif [ $SFLAG -eq 1 ]; then - "$STRIP" "$OUTPUT" || exit - fi - fi -fi diff --git a/tool/scripts/fat-aarch64 b/tool/scripts/fat-aarch64 new file mode 100755 index 000000000..ed8b5d8ab --- /dev/null +++ b/tool/scripts/fat-aarch64 @@ -0,0 +1,51 @@ +#!/bin/sh +# arm64 backend compiler for fatcosmocc + +CC="$COSMO/o/third_party/gcc/bin/aarch64-linux-musl-gcc" +CCFLAGS="-ffixed-x18 -ffixed-x28 -mno-outline-atomics" +LDFLAGS="-static -nostdlib -no-pie -Wl,-z,norelro" +APEFLAGS="-L$COSMOS/lib/.aarch64 -Wl,--gc-sections -Wl,-T,$COSMO/o/$MODE/ape/aarch64.lds $COSMO/o/$MODE/libc/crt/crt.o" +LDLIBS="$COSMO/o/$MODE/cosmopolitan.a" + +if [ x"$PROG" != x"${PROG%++}" ]; then + CC="$COSMO/o/third_party/gcc/bin/aarch64-linux-musl-g++" + CCFLAGS="$CCFLAGS -fno-rtti -fno-exceptions -fuse-cxa-atexit -fno-threadsafe-statics" + LDLIBS="$COSMO/o/$MODE/third_party/libcxx/libcxx.a $LDLIBS" +fi + +OPT= +FIRST=1 +OUTPUT= +INTENT=ld +for x; do + if [ $FIRST -eq 1 ]; then + set -- + FIRST=0 + fi + if [ x"$x" != x"${x#-O}" ]; then + OPT=$x + elif [ x"$x" = x"-c" ]; then + INTENT=cc + elif [ x"$x" != x"${x#-o}" ]; then + OUTPUT=${x#-o} + elif [ x"$x" = x"-march=native" ]; then + continue # doesn't make sense for a cross compiler + fi + set -- "$@" "$x" +done + +if [ x"$OPT" != x"-Os" ] && [ x"${MODE#aarch64-tiny}" != x"${MODE}" ]; then + # support --ftrace unless optimizing for size + CCFLAGS="$CCFLAGS -fpatchable-function-entry=7,6" +fi + +if [ $INTENT = cc ]; then + set -- "$CC" $CCFLAGS "$@" +else + set -- "$CC" $CCFLAGS $LDFLAGS $APEFLAGS $CPPFLAGS "$@" \ + $LDLIBS -Wl,-z,common-page-size=16384 -Wl,-z,max-page-size=16384 +fi + +printf '# %s\n(cd %s; %s)\n' "$ORIGINAL" "$PWD" "$*" >>"${TMPDIR:-/tmp}/build.log" +"$@" || exit +"$FIXUPOBJ" "$OUTPUT" || exit diff --git a/tool/scripts/fat-x86_64 b/tool/scripts/fat-x86_64 new file mode 100755 index 000000000..c5996c8a8 --- /dev/null +++ b/tool/scripts/fat-x86_64 @@ -0,0 +1,56 @@ +#!/bin/sh +# amd64 backend compiler for fatcosmocc + +CC="$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-gcc" +CCFLAGS="-mno-tls-direct-seg-refs -mno-red-zone" +LDFLAGS="-static -nostdlib -no-pie -Wl,-melf_x86_64" +APEFLAGS="-L$COSMOS/lib -Wl,--gc-sections -Wl,-T,$COSMO/o/$MODE/ape/public/ape.lds $COSMO/o/$MODE/ape/ape.o $COSMO/o/$MODE/libc/crt/crt.o" +LDLIBS="$COSMO/o/$MODE/cosmopolitan.a" + +if [ x"$PROG" != x"${PROG%++}" ]; then + CC="$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-g++" + CCFLAGS="$CCFLAGS -fno-rtti -fno-exceptions -fuse-cxa-atexit -fno-threadsafe-statics" + LDLIBS="$COSMO/o/$MODE/third_party/libcxx/libcxx.a $LDLIBS" +fi + +OPT= +FIRST=1 +OUTPUT= +INTENT=ld +for x; do + if [ $FIRST -eq 1 ]; then + set -- + FIRST=0 + fi + if [ x"$x" != x"${x#-O}" ]; then + OPT=$x + elif [ x"$x" = x"-c" ]; then + INTENT=cc + elif [ x"$x" != x"${x#-o}" ]; then + OUTPUT=${x#-o} + elif [ x"$x" = x"-march=native" ]; then + continue # doesn't make sense for a cross compiler + fi + set -- "$@" "$x" +done + +if [ x"$MODE" = x"nox87" ]; then + CCFLAGS="$CCFLAGS -mlong-double-64" +fi + +if [ x"$OPT" != x"-Os" ] && [ x"${MODE#tiny}" != x"${MODE}" ]; then + # support --ftrace unless optimizing for size + CCFLAGS="$CCFLAGS -fpatchable-function-entry=18,16" +fi + +if [ $INTENT = cc ]; then + set -- "$CC" $CCFLAGS "$@" +else + set -- "$CC" $CCFLAGS $LDFLAGS $APEFLAGS $CPPFLAGS "$@" \ + $LDLIBS -Wl,-z,common-page-size=4096 -Wl,-z,max-page-size=4096 \ + -fuse-ld=bfd +fi + +printf '# %s\n(cd %s; %s)\n' "$ORIGINAL" "$PWD" "$*" >>"${TMPDIR:-/tmp}/build.log" +"$@" || exit +"$FIXUPOBJ" "$OUTPUT" || exit diff --git a/tool/scripts/setup-cosmos b/tool/scripts/setup-cosmos new file mode 100755 index 000000000..1824813e6 --- /dev/null +++ b/tool/scripts/setup-cosmos @@ -0,0 +1,14 @@ +#!/bin/sh + +COSMOS=${COSMOS:-/opt/cosmos} + +for arch in "" .aarch64/; do + if [ ! -d "$COSMOS/lib/${arch}" ]; then + mkdir -p "$COSMOS/lib/${arch}" + fi + for lib in c dl gcc_s m pthread resolv rt dl z stdc++; do + if [ ! -f "$COSMOS/lib/${arch}lib${lib}.a" ]; then + printf '\041\074\141\162\143\150\076\012' >"$COSMOS/lib/${arch}lib${lib}.a" + fi + done +done