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.
This commit is contained in:
Justine Tunney 2023-08-11 22:52:11 -07:00
parent 8fc778162e
commit d53c335a45
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
35 changed files with 1151 additions and 525 deletions

View file

@ -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:

View file

@ -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

View file

@ -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 <jtunney@gmail.com>" >&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

1
ape/apeinstall.sh Symbolic link
View file

@ -0,0 +1 @@
../bin/ape-install

View file

@ -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

1
ape/apeuninstall.sh Symbolic link
View file

@ -0,0 +1 @@
../bin/ape-uninstall

132
bin/ape-install Executable file
View file

@ -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 <jtunney@gmail.com>" >&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

58
bin/ape-uninstall Executable file
View file

@ -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

1
bin/cosmoc++ Symbolic link
View file

@ -0,0 +1 @@
cosmocc

View file

@ -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 <<EOF
$PROG (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.
@ -67,39 +65,43 @@ EOF
exit 0
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
"$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

1
bin/fatcosmoc++ Symbolic link
View file

@ -0,0 +1 @@
fatcosmocc

310
bin/fatcosmocc Executable file
View file

@ -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 <cosmo.h>
# 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 <<EOF
$PROG (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
MODE=${MODE:-$m}
if [ x"$MODE" = x"" ]; then
MODE_AARCH64=aarch64
elif [ x"$MODE" = x"tiny" ]; then
MODE_AARCH64=aarch64-tiny
elif [ x"$MODE" = x"zero" ]; then
MODE_AARCH64=aarch64-zero
elif [ x"$MODE" = x"dbg" ]; then
MODE_AARCH64=aarch64-dbg
else
echo "$PROG: build MODE=$MODE not supported by fatcosmocc" >&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

1
bin/unknown-unknown-cosmo-ar Executable file
View file

@ -0,0 +1 @@
#!/bin/sh

View file

@ -0,0 +1 @@
fatcosmocc

View file

@ -0,0 +1 @@
fatcosmocc

View file

@ -0,0 +1 @@
fatcosmocc

View file

@ -0,0 +1 @@
fatcosmocc

View file

@ -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" "$@"

18
bin/x86_64-unknown-cosmo-ar Executable file
View file

@ -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" "$@"

13
bin/x86_64-unknown-cosmo-as Executable file
View file

@ -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" "$@"

View file

@ -0,0 +1 @@
cosmocc

1
bin/x86_64-unknown-cosmo-cc Symbolic link
View file

@ -0,0 +1 @@
cosmocc

View file

@ -0,0 +1 @@
cosmocc

View file

@ -0,0 +1 @@
cosmocc

13
bin/x86_64-unknown-cosmo-ld Executable file
View file

@ -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" "$@"

View file

@ -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" "$@"

13
bin/x86_64-unknown-cosmo-strip Executable file
View file

@ -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" "$@"

View file

@ -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 \

View file

@ -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);
}

View file

@ -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_

View file

@ -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

184
tool/build/march-native.c Normal file
View file

@ -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
}

View file

@ -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

View file

@ -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 <cosmo.h>
# 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

51
tool/scripts/fat-aarch64 Executable file
View file

@ -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

56
tool/scripts/fat-x86_64 Executable file
View file

@ -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

14
tool/scripts/setup-cosmos Executable file
View file

@ -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