Redesign cosmocc toolchain

The `cosmocc` compiler is now being distributed as a self-contained
toolchain that's path-agnostic and it no longer requires you clone the
Cosmop repo to use it. The bin/ folder has been deleted from the mono
repo. The `fatcosmocc` command has been renamed to `cosmocc`. MacOS
support now works very well.
This commit is contained in:
Justine Tunney 2023-11-11 14:04:26 -08:00
parent 3802428026
commit 291103ad8d
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
71 changed files with 2437 additions and 1398 deletions

View file

@ -0,0 +1 @@
aarch64-linux-cosmo-addr2line

View file

@ -0,0 +1 @@
aarch64-linux-cosmo-ar

View file

@ -0,0 +1 @@
aarch64-linux-cosmo-as

View file

@ -0,0 +1 @@
cosmocross

View file

@ -0,0 +1 @@
cosmocross

View file

@ -0,0 +1,15 @@
#!/bin/sh
FIRST=1
for x; do
if [ $FIRST -eq 1 ]; then
set --
FIRST=0
fi
if [ x"$x" = x"-s" ]; then
continue
fi
set -- "$@" "$x"
done
exec install "$@"

View file

@ -0,0 +1 @@
aarch64-linux-cosmo-nm

View file

@ -0,0 +1 @@
aarch64-linux-cosmo-objcopy

View file

@ -0,0 +1 @@
aarch64-linux-cosmo-objdump

View file

@ -0,0 +1 @@
aarch64-linux-cosmo-strip

15
tool/cosmocc/bin/cosmoaddr2line Executable file
View file

@ -0,0 +1,15 @@
#!/bin/sh
BIN=${0%/*}
set -- -apifCe "$@"
if [ -n "$ADDR2LINE" ]; then
exec "$ADDR2LINE" "$@"
fi
for arch in x86_64 aarch64; do
"$BIN/$arch-linux-cosmo-addr2line" "$@" 2>/dev/null && exit
done
echo "error: addr2line failed" >&2
exit 1

108
tool/cosmocc/bin/cosmoar Executable file
View file

@ -0,0 +1,108 @@
#!/bin/sh
BIN=${0%/*}
PROG=${0##*/}
fatal_error() {
echo "$PROG: $1" >&2
exit 1
}
AR_X86_64="$BIN/x86_64-linux-cosmo-ar"
AR_AARCH64="$BIN/aarch64-linux-cosmo-ar"
if [ "$1" = "--version" ]; then
# note: only the underlying gnu compiler binaries are gpl
# our shell script is released with the isc license
cat <<EOF
$PROG (GNU Binutils) 2.38
Copyright (C) 2022 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) any later version.
This program has absolutely no warranty.
EOF
exit 0
elif [ "$1" = "--help" ]; then
"$AR_X86_64" --help |
sed "s!$AR_X86_64!$PROG!g" 2>/dev/null ||
"$AR_X86_64" --help
exit
fi
FIRST=1
STATE=0
OUTPUT_X86_64=
OUTPUT_AARCH64=
INPUTS=
for x; do
if [ $FIRST -eq 1 ]; then
set --
FIRST=0
fi
if [ $STATE -eq 0 ]; then
if [ x"$x" != x"${x#--*}" ]; then # startswith(x, "--")
set -- "$@" "$x" # this is a flag
else
set -- "$@" "$x" # command argument, e.g. rcu, rcsD
STATE=1
fi
elif [ $STATE -eq 1 ]; then
OUTPUT_X86_64=$x
STATE=2
elif [ x"$x" != x"${x#* }" ]; then
fatal_error "input arguments containing spaces unsupported"
elif [ x"$x" != x"${x#@}" ]; then
fatal_error "input argument @file not supported yet"
elif [ -z "$INPUTS" ]; then
INPUTS=$x
else
INPUTS="$INPUTS $x"
fi
done
if [ -z "$OUTPUT_X86_64" ]; then
fatal_error "missing output path"
fi
mangle_object_path() {
path=$1
arch=$2
outdir=${path%/*}
outbas=${path##*/}
if [ x"$outdir" = x"$path" ]; then
outdir=
elif [ -n "$outdir" ]; then
outdir="$outdir/"
fi
if [ ! -d "$outdir.$arch" ]; then
mkdir -p "$outdir.$arch" || Exit
fi
mangled_path="${outdir}.$arch/$outbas"
}
OBJECTS_X86_64=
OBJECTS_AARCH64=
for x in $INPUTS; do
if [ ! -f "$x" ]; then
fatal_error "$x: no such file"
fi
mangle_object_path "$x" aarch64
if [ ! -f "$mangled_path" ]; then
fatal_error "$x: missing concomitant $mangled_path file"
fi
OBJECTS_X86_64="${OBJECTS_X86_64} $x"
OBJECTS_AARCH64="${OBJECTS_AARCH64} $mangled_path"
done
mangle_object_path "$OUTPUT_X86_64" aarch64
OUTPUT_AARCH64="$mangled_path"
"$AR_X86_64" "$@" "$OUTPUT_X86_64" $OBJECTS_X86_64 &
pid1=$!
"$AR_AARCH64" "$@" "$OUTPUT_AARCH64" $OBJECTS_AARCH64 &
pid2=$!
if ! wait $pid1; then
kill $pid2 2>/dev/null
wait
exit 1
fi
wait $pid2 || exit

1
tool/cosmocc/bin/cosmoc++ Symbolic link
View file

@ -0,0 +1 @@
cosmocc

499
tool/cosmocc/bin/cosmocc Executable file
View file

@ -0,0 +1,499 @@
#!/bin/sh
# fat cosmopolitan c/c++ compiler
# https://github.com/jart/cosmopolitan
# https://cosmo.zip/
BIN=${0%/*}
PROG=${0##*/}
ORIGINAL="$0 $*"
GCC_VERSION=11.2.0
TMPDIR=${TMPDIR:-/tmp}
if [ "$1" = "--version" ]; then
cat <<EOF
$PROG (GCC) $GCC_VERSION
Copyright (c) 2023 Justine Alexandra Roberts Tunney
Cosmopolitan Libc and LLVM libcxx/compiler-rt are subject to non-GPL
notice licenses, e.g. ISC, MIT, etc. Your compiled programs must embed
our copyright notices. This toolchain is configured to do so default.
Cosmopolitan comes with absolutely NO WARRANTY of any kind.
For more information, see the Cosmopolitan LICENSE files.
Copyright (C) 2019 Free Software Foundation, Inc.
This launches GNU GCC/Binutils subprocesses, which is free software; see
Cosmopolitan's third_party/gcc/ for source code and copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
EOF
exit
fi
if [ "$1" = "--help" ]; then
if [ -t 1 ]; then
exec less "$BIN/../README.md"
else
exec cat "$BIN/../README.md"
fi
fi
TEMP_FILES=
SAVE_TEMPS=0
Exit() {
rc=${1:-$?}
if [ $SAVE_TEMPS -eq 0 ]; then
rm -f $TEMP_FILES
fi
exit $rc
}
show_warning() {
echo "$PROG: warning: $1" >&2
}
fatal_error() {
echo "$PROG: fatal error: $1" >&2
echo "compilation terminated." >&2
Exit 1
}
log_original() {
if [ -n "$BUILDLOG" ]; then
printf '# %s\n' "$ORIGINAL" >>"$BUILDLOG"
fi
}
log_command() {
if [ -n "$BUILDLOG" ]; then
printf '(cd %s; %s)\n' "$PWD" "$*" >>"$BUILDLOG"
fi
}
if [ x"$TMPDIR" != x"${TMPDIR#* }" ]; then
fatal_error '$TMPDIR containing spaces not supported'
elif [ ! -d "$TMPDIR" ]; then
if ! mkdir -p "$TMPDIR" 2>/dev/null; then
fatal_error "$TMPDIR: not a directory"
fi
fi
OPT=
ARGS=
FLAGS=
OUTPUT=
MCOSMO=0
INTENT=ld
NEED_JOIN=
NEED_EQUAL=
NEED_OUTPUT=
APELINKFLAGS=
FLAGS_X86_64=
FLAGS_AARCH64=
INPUT_FILE_COUNT=0
for x; do
if [ x"$x" != x"${x#* }" ]; then
fatal_error "arguments containing spaces unsupported: $x"
fi
if [ -n "$NEED_OUTPUT" ]; then
NEED_OUTPUT=
OUTPUT=$x
continue
elif [ -n "$NEED_JOIN" ]; then
x="${NEED_JOIN}${x}"
NEED_JOIN=
elif [ -n "$NEED_EQUAL" ]; then
x="${NEED_EQUAL}=${x}"
NEED_EQUAL=
elif [ x"$x" = x"-" ] || # is alias for stdin
[ x"$x" = x"${x#-*}" ]; then # !startswith(x, "-")
if [ x"$x" != x"${x%.s}" ] ||
[ x"$x" != x"${x%.S}" ]; then
fatal_error "$x: assembler input files not supported"
elif [ x"$x" != x"${x%.so}" ] ||
[ x"$x" != x"${x%.dll}" ] ||
[ x"$x" != x"${x%.dylib}" ]; then
fatal_error "$x: dynamic shared object input files not supported"
elif [ x"$x" != x"-" ] && [ ! -f "$x" ]; then
fatal_error "$x: no such file"
fi
INPUT_FILE_COUNT=$((INPUT_FILE_COUNT + 1))
ARGS="$ARGS $x" # don't add to $FLAGS array
continue
elif [ x"$x" = x"-o" ]; then
NEED_OUTPUT=1
continue
elif [ x"$x" != x"${x#-o}" ]; then # startswith(x, "-o")
OUTPUT=${x#-o}
continue
elif [ x"$x" != x"${x#-O}" ]; then # startswith(x, "-O")
OPT=$x
elif [ x"$x" = x"-c" ]; then
INTENT=cc
elif [ x"$x" = x"-E" ]; then
INTENT=cpp
elif [ x"$x" = x"-s" ]; then
APELINKFLAGS="$APELINKFLAGS -s"
continue
elif [ x"$x" = x"-v" ]; then
exec 3<&2 # dup2(2, 3) b/c stderr will be redirected later
BUILDLOG=/dev/fd/3
continue
elif [ x"$x" = x"-save-temps" ]; then
SAVE_TEMPS=1
elif [ x"$x" = x"-mcosmo" ]; then
MCOSMO=1
continue
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 -foptimize-sibling-calls"
elif [ x"$x" = x"-r" ] ||
[ x"$x" = x"-S" ] ||
[ 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
fatal_error "$x flag not supported"
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
elif [ x"$x" = x"-march=native" ]; then
fatal_error "-march=native can't be used when building fat binaries"
elif [ x"$x" != x"${x#-Xx86_64}" ]; then
x=${x#-Xx86_64} # e.g. -Xx86_64,-msse3,-mavx,-mavx2,-mf16c,-mfma
FLAGS_X86_64="$FLAGS_X86_64 ${x//,/ }"
continue
elif [ x"$x" != x"${x#-Xaarch64}" ]; then
x=${x#-Xaarch64}
FLAGS_aarch64="$FLAGS_aarch64 ${x//,/ }"
continue
elif [ x"$x" = x"-dumpversion" ]; then
echo $GCC_VERSION
Exit 0
elif [ x"$x" = x"-e" ] ||
[ x"$x" = x"-z" ] ||
[ x"$x" = x"-T" ] ||
[ x"$x" = x"-L" ] ||
[ x"$x" = x"-I" ] ||
[ x"$x" = x"-D" ] ||
[ x"$x" = x"-U" ] ||
[ x"$x" = x"-iquote" ] ||
[ x"$x" = x"-isystem" ] ||
[ x"$x" = x"-include" ]; then
NEED_JOIN=$x
continue
elif [ x"$x" = x"--param" ]; then
NEED_EQUAL=$x
continue
fi
FLAGS="$FLAGS $x"
ARGS="$ARGS $x"
done
if [ $INPUT_FILE_COUNT -eq 0 ]; then
fatal_error "no input files"
elif [ -z "$INPUT" ] &&
[ $INTENT != ld ] &&
[ $INPUT_FILE_COUNT -gt 1 ]; then
fatal_error "cannot specify '-o' with '-c', or '-E' with multiple files"
fi
PLATFORM="-D__COSMOPOLITAN__ -D__COSMOCC__ -D__FATCOSMOCC__"
PREDEF="-include libc/integral/normalize.inc"
CPPFLAGS="-fno-pie -nostdinc -fno-math-errno -isystem $BIN/../include"
CFLAGS="-fportcosmo -fno-dwarf2-cfi-asm -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-semantic-interposition"
LDFLAGS="-static -nostdlib -no-pie -fuse-ld=bfd -Wl,-z,norelro -Wl,--gc-sections"
PRECIOUS="-fno-omit-frame-pointer"
if [ x"$OPT" != x"-Os" ] && [ x"$MODE" != x"tiny" ]; then
CFLAGS="$CFLAGS -fno-optimize-sibling-calls -mno-omit-leaf-frame-pointer"
fi
CC_X86_64="$BIN/x86_64-linux-cosmo-gcc"
CC_AARCH64="$BIN/aarch64-linux-cosmo-gcc"
if [ x"$PROG" != x"${PROG%++}" ]; then
CC_X86_64="$BIN/x86_64-linux-cosmo-g++"
CC_AARCH64="$BIN/aarch64-linux-cosmo-g++"
CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -fuse-cxa-atexit"
fi
CRT_X86_64="$BIN/../x86_64-linux-cosmo/lib/ape.o $BIN/../x86_64-linux-cosmo/lib/crt.o"
CPPFLAGS_X86_64="$CPPFLAGS -mno-red-zone"
CFLAGS_X86_64="$CFLAGS -mno-tls-direct-seg-refs"
LDFLAGS_X86_64="$LDFLAGS -L$BIN/../x86_64-linux-cosmo/lib -Wl,-T,$BIN/../x86_64-linux-cosmo/lib/ape.lds -Wl,-z,common-page-size=4096 -Wl,-z,max-page-size=16384"
LDLIBS_X86_64="-lcosmo"
if [ $MCOSMO -eq 1 ]; then
CPPFLAGS_X86_64="${CPPFLAGS_X86_64} -D_COSMO_SOURCE"
fi
CRT_AARCH64="$BIN/../aarch64-linux-cosmo/lib/crt.o"
CPPFLAGS_AARCH64="$CPPFLAGS"
CFLAGS_AARCH64="$CFLAGS -ffixed-x18 -ffixed-x28 -mno-outline-atomics"
LDFLAGS_AARCH64="$LDFLAGS -L$BIN/../aarch64-linux-cosmo/lib -Wl,-T,$BIN/../aarch64-linux-cosmo/lib/aarch64.lds -Wl,-z,common-page-size=16384 -Wl,-z,max-page-size=16384"
LDLIBS_AARCH64="-lcosmo"
if [ x"$OPT" != x"-Os" ] && [ x"$MODE" != x"tiny" ]; then
CFLAGS_X86_64="${CFLAGS_X86_64} -fpatchable-function-entry=18,16"
CFLAGS_AARCH64="${CFLAGS_AARCH64} -fpatchable-function-entry=7,6"
fi
if [ x"$PROG" != x"${PROG%++}" ]; then
LDLIBS_X86_64="-lcxx ${LDLIBS_X86_64}"
LDLIBS_AARCH64="-lcxx ${LDLIBS_AARCH64}"
fi
log_original
if [ $INTENT = cpp ]; then
if [ -n "$OUTPUT" ]; then
ARGS="$ARGS -o$OUTPUT"
fi
set -- \
"$CC_X86_64" \
-U__k8 \
-U__k8__ \
-U__amd64 \
-U__amd64__ \
-U__x86_64 \
-U__x86_64__ \
-U__SSE__ \
-U__SSE2__ \
-U__SSE2_MATH__ \
-mno-red-zone \
$PLATFORM \
$CPPFLAGS \
$ARGS
log_command "$@"
exec "$@"
fi
mangle_object_path() {
path=$1
arch=$2
outdir=${path%/*}
outbas=${path##*/}
if [ x"$outdir" = x"$path" ]; then
outdir=
elif [ -n "$outdir" ]; then
outdir="$outdir/"
fi
if [ ! -d "$outdir.$arch" ]; then
mkdir -p "$outdir.$arch" || Exit
fi
mangled_path="${outdir}.$arch/$outbas"
}
mktemper() {
"$BIN/mktemper" \
"$TMPDIR/fatcosmocc.XXXXXXXXXXXXX$1"
}
build_object() {
out2=$(mktemper .txt) || Exit
TEMP_FILES="${TEMP_FILES} $out2"
(
set -- \
"$CC_X86_64" \
-o"$OUTPUT_X86_64" \
$PLATFORM \
$PREDEF \
$CFLAGS_X86_64 \
$CPPFLAGS_X86_64 \
"$@" \
$FLAGS_X86_64 \
$PRECIOUS
log_command "$@"
"$@" || exit
set -- \
"$BIN/fixupobj" \
"$OUTPUT_X86_64"
log_command "$@"
exec "$@"
) &
pid1=$!
(
set -- \
"$CC_AARCH64" \
-o"$OUTPUT_AARCH64" \
$PLATFORM \
$PREDEF \
$CFLAGS_AARCH64 \
$CPPFLAGS_AARCH64 \
"$@" \
$FLAGS_AARCH64 \
$PRECIOUS
log_command "$@"
"$@" || exit
set -- \
"$BIN/fixupobj" \
"$OUTPUT_AARCH64"
log_command "$@"
exec "$@"
) 2>"$out2" &
pid2=$!
if ! wait $pid1; then
kill $pid2 2>/dev/null
wait
Exit 1
fi
if ! wait $pid2; then
echo "$PROG: x86_64 succeeded but aarch64 failed to build object" >&2
cat "$out2" >&2
Exit 1
fi
}
# turn source files into objects
LDARGS_X86_64=
LDARGS_AARCH64=
for x in $ARGS; do
if [ x"$x" != x"-" ] && # is alias for stdin
[ x"$x" != x"${x#-*}" ]; then # startswith(x, "-")
# this argument is a flag
LDARGS_X86_64="${LDARGS_X86_64} $x"
if [ x"$x" != x"${x#-L}" ]; then # startswith(x, "-L")
x="$x/.aarch64"
fi
LDARGS_AARCH64="${LDARGS_AARCH64} $x"
else
# this argument is an input file
if [ x"$x" != x"${x%.o}" ] ||
[ x"$x" != x"${x%.a}" ]; then
if [ $INTENT = cc ]; then
show_warning "$x: linker input file unused because linking not done"
else
mangle_object_path "$x" aarch64
if [ ! -f "$mangled_path" ]; then
fatal_error "$x: linker input missing concomitant $mangled_path file"
fi
LDARGS_X86_64="${LDARGS_X86_64} $x"
LDARGS_AARCH64="${LDARGS_AARCH64} $mangled_path"
fi
elif [ $INTENT = cc ]; then
if [ -n "$OUTPUT" ]; then
# e.g. `cc -c -o bar.o foo.c` is specified by user
OUTPUT_X86_64=$OUTPUT
mangle_object_path "$OUTPUT" aarch64
OUTPUT_AARCH64="$mangled_path"
build_object $FLAGS -c "$x"
else
# e.g. `cc -c dir/foo.c` builds foo.o
o=${x##*/}
OUTPUT_X86_64="${o%.*}.o"
mangle_object_path "${o%.*}.o" aarch64
OUTPUT_AARCH64="$mangled_path"
build_object $FLAGS -c "$x"
fi
else
# e.g. `cc foo.c` should build a.out
if [ -z "$OUTPUT" ]; then
OUTPUT=a.out
fi
# e.g. `cc -o foo foo.c` should *not* build foo.o
OUTPUT_X86_64=$(mktemper .o) || Exit
OUTPUT_AARCH64=$(mktemper .o) || Exit
TEMP_FILES="${TEMP_FILES} ${OUTPUT_X86_64} ${OUTPUT_AARCH64}"
build_object $FLAGS -c "$x"
LDARGS_X86_64="${LDARGS_X86_64} ${OUTPUT_X86_64}"
LDARGS_AARCH64="${LDARGS_AARCH64} ${OUTPUT_AARCH64}"
fi
fi
done
if [ $INTENT != ld ]; then
Exit
fi
OUTPUT_X86_64=$(mktemper ".com.dbg") || Exit
OUTPUT_AARCH64=$(mktemper ".aarch64.elf") || Exit
out2=$(mktemper .txt) || Exit
TEMP_FILES="${TEMP_FILES} $out2"
(
set -- \
"$CC_X86_64" \
-o"$OUTPUT_X86_64"\
$CRT_X86_64 \
$LDFLAGS_X86_64 \
$LDARGS_X86_64 \
$LDLIBS_X86_64
log_command "$@"
"$@" || exit
set -- \
"$BIN/fixupobj" \
"$OUTPUT_X86_64"
log_command "$@"
exec "$@"
) &
pid1=$!
(
set -- \
"$CC_AARCH64" \
-o"$OUTPUT_AARCH64"\
$CRT_AARCH64 \
$LDFLAGS_AARCH64 \
$LDARGS_AARCH64 \
$LDLIBS_AARCH64
log_command "$@"
"$@" || exit
set -- \
"$BIN/fixupobj" \
"$OUTPUT_AARCH64"
log_command "$@"
exec "$@"
) 2>"$out2" &
pid2=$!
if ! wait $pid1; then
kill $pid2 2>/dev/null
wait
Exit 1
fi
if ! wait $pid2; then
echo "$PROG: x86_64 succeeded but aarch64 failed to link executable" >&2
cat "$out2" >&2
Exit 1
fi
set -- \
"$BIN/apelink" \
-l "$BIN/ape.elf" \
-l "$BIN/ape.aarch64" \
-M "$BIN/ape-m1.c" \
-o "$OUTPUT" \
$APELINKFLAGS \
"$OUTPUT_X86_64" \
"$OUTPUT_AARCH64"
log_command "$@"
"$@" || Exit
set -- \
"$BIN/pecheck" "$OUTPUT"
log_command "$@"
"$@" || Exit
if [ $INTENT = ld ] && [ $SAVE_TEMPS -eq 0 ]; then
mv -f "$OUTPUT_X86_64" "${OUTPUT%.com}.com.dbg" || Exit
mv -f "$OUTPUT_AARCH64" "${OUTPUT%.com}.aarch64.elf" || Exit
fi
Exit

238
tool/cosmocc/bin/cosmocross Executable file
View file

@ -0,0 +1,238 @@
#!/bin/sh
# cosmopolitan c/c++ cross compiler
# https://github.com/jart/cosmopolitan
# https://cosmo.zip/
BIN=${0%/*}
PROG=${0##*/}
GCC_VERSION=11.2.0
if [ "$1" = "--version" ]; then
cat <<EOF
$PROG (GCC) $GCC_VERSION
Copyright (c) 2023 Justine Alexandra Roberts Tunney
Cosmopolitan Libc and LLVM libcxx/compiler-rt are subject to non-GPL
notice licenses, e.g. ISC, MIT, etc. Your compiled programs must embed
our copyright notices. This toolchain is configured to do so default.
Cosmopolitan comes with absolutely NO WARRANTY of any kind.
For more information, see the Cosmopolitan LICENSE files.
Copyright (C) 2019 Free Software Foundation, Inc.
This launches GNU GCC/Binutils subprocesses, which is free software; see
Cosmopolitan's third_party/gcc/ for source code and copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
EOF
exit
fi
if [ "$1" = "--help" ]; then
if [ -t 1 ]; then
exec less "$BIN/../README.md"
else
exec cat "$BIN/../README.md"
fi
fi
fatal_error() {
echo "$PROG: fatal error: $1" >&2
echo "compilation terminated." >&2
exit 1
}
log_command() {
if [ -n "$BUILDLOG" ]; then
printf '# %s\n(cd %s; %s)\n' "$ORIGINAL" "$PWD" "$*" >>"$BUILDLOG"
fi
}
ORIGINAL="$0 $*"
PLATFORM="-D__COSMOPOLITAN__ -D__COSMOCC__"
PREDEF="-include libc/integral/normalize.inc"
CFLAGS="-fportcosmo -fno-dwarf2-cfi-asm -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-semantic-interposition"
CPPFLAGS="-fno-pie -nostdinc -fno-math-errno -isystem $BIN/../include"
LDFLAGS="-static -no-pie -nostdlib -fuse-ld=bfd"
APEFLAGS="-Wl,--gc-sections"
PRECIOUS="-fno-omit-frame-pointer"
CROSS=1
ARCH=${PROG%%-*}
if [ x"$ARCH" = x"$PROG" ]; then
fatal_error "cosmocross must be run via cross compiler"
fi
CC="$BIN/$ARCH-linux-cosmo-gcc"
CRT="$BIN/../$ARCH-linux-cosmo/lib/crt.o"
LDLIBS="-lcosmo"
LDFLAGS="$LDFLAGS -L$BIN/../$ARCH-linux-cosmo/lib"
if [ x"$PROG" != x"${PROG%++}" ]; then
CC="$BIN/$ARCH-linux-cosmo-g++"
CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -fuse-cxa-atexit"
LDLIBS="-lcxx $LDLIBS"
fi
PAGESZ=4096
if [ x"$ARCH" = x"x86_64" ]; then
OBJCOPYFLAGS="-S -O binary"
CRT="$BIN/../$ARCH-linux-cosmo/lib/ape-no-modify-self.o $CRT"
CPPFLAGS="$CPPFLAGS -mno-red-zone"
CFLAGS="$CFLAGS -mno-tls-direct-seg-refs"
LDFLAGS="$LDFLAGS -Wl,-T,$BIN/../$ARCH-linux-cosmo/lib/ape.lds"
elif [ x"$ARCH" = x"aarch64" ]; then
OBJCOPYFLAGS="-S"
PAGESZ=16384
CFLAGS="$CFLAGS -ffixed-x18 -ffixed-x28 -mno-outline-atomics"
LDFLAGS="$LDFLAGS -Wl,-T,$BIN/../$ARCH-linux-cosmo/lib/aarch64.lds"
else
fatal_error "$ARCH: unsupported architecture"
fi
LDFLAGS="$LDFLAGS -Wl,-z,common-page-size=$PAGESZ -Wl,-z,max-page-size=16384"
OPT=
FIRST=1
OUTPUT=
SFLAG=0
INTENT=ld
GOT_SOME=0
NEED_OUTPUT=
RELOCATABLE=0
for x; do
if [ $FIRST -eq 1 ]; then
set --
FIRST=0
fi
if [ -n "$NEED_OUTPUT" ]; then
NEED_OUTPUT=
OUTPUT=$x
set -- "$@" "$x"
continue
fi
if [ x"$x" = x"-" ] || # is an argument
[ x"$x" = x"${x#-*}" ]; then # !startswith(x, "-")
GOT_SOME=1
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"-mcosmo" ]; then
CPPFLAGS="$CPPFLAGS -D_COSMO_SOURCE"
continue
elif [ x"$x" != x"${x#-o}" ]; then
OUTPUT=${x#-o}
elif [ x"$x" = x"-fpic" ]; then
continue
elif [ x"$x" = x"-fPIC" ]; then
continue
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" ]; 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."
set -- "$@" -momit-leaf-frame-pointer -foptimize-sibling-calls
continue
elif [ x"$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
if [ $CROSS -eq 0 ]; then
set -- "$@" $("$BIN/march-native")
else
fatal_error "-march=native can't be used when cross compiling"
fi
continue
elif [ x"$x" = x"-dumpversion" ]; then
echo $GCC_VERSION
exit 0
elif [ x"$x" = x"-Wl,--version" ]; then
GOT_SOME=1
elif [ x"$x" = x"-dumpmachine" ]; then
GOT_SOME=1
fi
set -- "$@" "$x"
done
if [ "$GOT_SOME" -eq 0 ]; then
fatal_error "no input files"
fi
if [ $RELOCATABLE -eq 1 ]; then
LDFLAGS="$LDFLAGS -r"
fi
# support --ftrace unless optimizing for size
if [ x"$OPT" != x"-Os" ] && # $OPT != -Os
[ x"${MODE%tiny}" = x"${MODE}" ]; then # $MODE not in (tiny, aarch64-tiny)
if [ x"$ARCH" = x"x86_64" ]; then
CFLAGS="$CFLAGS -fpatchable-function-entry=18,16"
elif [ x"$ARCH" = x"aarch64" ]; then
CFLAGS="$CFLAGS -fpatchable-function-entry=7,6"
fi
fi
# maximize frame pointers unless optimizing for size
if [ x"$OPT" != x"-Os" ] && # $OPT != "-Os"
[ x"$MODE" != x"${MODE%tiny}" ]; then # endswith($MODE, "tiny")
CFLAGS="$CFLAGS -fno-optimize-sibling-calls -mno-omit-leaf-frame-pointer"
fi
if [ $INTENT = cpp ]; then
set -- "$CC" $PLATFORM $CPPFLAGS "$@"
elif [ $INTENT = cc ]; then
set -- "$CC" $PLATFORM $PREDEF $CFLAGS $CPPFLAGS "$@" $PRECIOUS
else
set -- "$CC" $PLATFORM $PREDEF $CFLAGS $CPPFLAGS $CRT "$@" $LDFLAGS $LDLIBS $PRECIOUS
fi
log_command "$@"
"$@" || exit
if [ -n "$OUTPUT" ] && [ -f "$OUTPUT" ]; then
if [ $INTENT = cc ] || [ $INTENT = ld ]; then
"$BIN/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
"$BIN/$ARCH-linux-cosmo-objcopy" \
$OBJCOPYFLAGS \
"$OUTPUT.dbg" \
"$OUTPUT" || exit
"$BIN/zipcopy" \
"$OUTPUT.dbg" \
"$OUTPUT" || exit
elif [ $SFLAG -eq 1 ]; then
"$BIN/$ARCH-linux-cosmo-strip" \
"$OUTPUT" || exit
fi
fi
fi

100
tool/cosmocc/bin/cosmoinstall Executable file
View file

@ -0,0 +1,100 @@
#!/bin/sh
# the `install -s` strip flag provided by gnu coreutils surprisngly
# enough understands the portable executable format however it will
# silently corrupt any actually portable executable it touches, due
# to how it overwrites the whole mz header and removes the dos stub
FIRST=1
for x; do
if [ $FIRST -eq 1 ]; then
set --
FIRST=0
fi
if [ x"$x" = x"-s" ]; then
continue
fi
set -- "$@" "$x"
done
# now magically copy multi-architecture build artifacts
if [ $# -gt 1 ]; then
# parse `install [$flags]... $src $dst`
i=0
n=$(( $# - 2 ))
dst=
src=
flags=
for x; do
if [ x"$x" != x"${x#* }" ]; then
# give up if any arguments contain spaces
exec install "$@"
fi
src=$dst
dst=$x
if [ $i -lt $n ]; then
flags="$flags $x"
fi
i=$(( i + 1 ))
done
arch=aarch64
# turn:
# install -c -m 644 foo.a /usr/lib/foo.a
# into:
# install -c -m 644 foo.a /usr/lib/foo.a
# install -c -m 644 .aarch/foo.a /usr/lib/.aarch/foo.a
if [ x"${dst##*/}" = x"${src##*/}" ] && # basenames are equal
[ x"$dst" != x"${dst%.a}" ]; then # specifies static archive
srcdir=${src%/*}
srcbas=${dst##*/}
if [ x"$srcdir" = x"$src" ]; then
srcdir=
elif [ -n "$srcdir" ]; then
srcdir="$srcdir/"
fi
if [ -f "$srcdir.$arch/$srcbas" ]; then
dstdir=${dst%/*}
dstbas=${dst##*/}
if [ x"$dstdir" = x"$dst" ]; then
dstdir=
elif [ -n "$dstdir" ]; then
dstdir="$dstdir/"
fi
if [ ! -d "$dstdir.$arch" ]; then
mkdir -p "$dstdir.$arch" || exit
fi
install $flags $src $dst || exit
exec install $flags \
"$srcdir.$arch/$srcbas" \
"$dstdir.$arch/$dstbas"
fi
fi
# turn:
# install -c -m 644 foo.a /usr/lib
# into:
# install -c -m 644 foo.a /usr/lib
# install -c -m 644 .aarch/foo.a /usr/lib/.aarch
arch=aarch64
if [ x"$src" != x"${src%.a}" ] && [ -d "$dst" ]; then
srcdir=${src%/*}
srcbas=${dst##*/}
if [ x"$srcdir" = x"$src" ]; then
srcdir=
elif [ -n "$srcdir" ]; then
srcdir="$srcdir/"
fi
if [ -f "$srcdir.$arch/$srcbas" ]; then
if [ ! -d "$dst/.$arch" ]; then
mkdir -p "$dst/.$arch" || exit
fi
install $flags $src $dst || exit
exec install $flags "$srcdir.$arch/$srcbas" "$dst/.$arch"
fi
fi
fi
exec install "$@"

View file

@ -0,0 +1 @@
cosmoar

View file

@ -0,0 +1 @@
cosmocc

View file

@ -0,0 +1 @@
cosmocc

View file

@ -0,0 +1 @@
cosmoinstall

View file

@ -0,0 +1 @@
x86_64-linux-cosmo-addr2line

View file

@ -0,0 +1 @@
x86_64-linux-cosmo-ar

View file

@ -0,0 +1 @@
x86_64-linux-cosmo-as

View file

@ -0,0 +1 @@
cosmocross

View file

@ -0,0 +1 @@
cosmocross

View file

@ -0,0 +1,15 @@
#!/bin/sh
FIRST=1
for x; do
if [ $FIRST -eq 1 ]; then
set --
FIRST=0
fi
if [ x"$x" = x"-s" ]; then
continue
fi
set -- "$@" "$x"
done
exec install "$@"

View file

@ -0,0 +1 @@
x86_64-linux-cosmo-nm

View file

@ -0,0 +1 @@
x86_64-linux-cosmo-objcopy

View file

@ -0,0 +1 @@
x86_64-linux-cosmo-objdump

View file

@ -0,0 +1 @@
x86_64-linux-cosmo-strip