cosmopolitan/tool/cosmocc/bin/cosmocc
Justine Tunney c9152b6f14
Release Cosmopolitan v3.8.0
This change switches c++ exception handling from sjlj to standard dwarf.
It's needed because clang for aarch64 doesn't support sjlj. It turns out
that libunwind had a bare-metal configuration that made this easy to do.

This change gets the new experimental cosmocc -mclang flag in a state of
working so well that it can now be used to build all of llamafile and it
goes 3x faster in terms of build latency, without trading away any perf.

The int_fast16_t and int_fast32_t types are now always defined as 32-bit
in the interest of having more abi consistency between cosmocc -mgcc and
-mclang mode.
2024-08-30 20:14:07 -07:00

696 lines
18 KiB
Bash
Executable file

#!/bin/sh
# fat cosmopolitan c/c++ compiler
# https://github.com/jart/cosmopolitan
# https://cosmo.zip/
BIN=${0%/*}
PROG=${0##*/}
ORIGINAL="$0 $*"
GCC_VERSION=14.1.0
TMPDIR=${TMPDIR:-/tmp}
if [ "$1" = "--version" ]; then
cat <<EOF
$PROG (GCC) $GCC_VERSION
Copyright (c) 2024 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 by default.
Cosmopolitan comes with absolutely NO WARRANTY of any kind.
For more information, see the Cosmopolitan LICENSE files.
Copyright (C) 2022 Free Software Foundation, Inc.
This launches GNU GCC/Binutils subprocesses, which is free software; see
cosmocc's LICENSE files 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
use_gcc() {
CLANG=0
CC_X86_64="$BIN/x86_64-linux-cosmo-gcc"
CC_AARCH64="$BIN/aarch64-linux-cosmo-gcc"
CXX_X86_64="$BIN/x86_64-linux-cosmo-g++"
CXX_AARCH64="$BIN/aarch64-linux-cosmo-g++"
TARGET_X86_64=
TARGET_AARCH64=
FPORTCOSMO="-fportcosmo"
FNO_INLINE_FUNCTIONS_CALLED_ONCE="-fno-inline-functions-called-once"
}
use_clang() {
CLANG=1
CC_X86_64="$BIN/cosmo-clang"
CC_AARCH64="$BIN/cosmo-clang"
CXX_X86_64="$BIN/cosmo-clang"
CXX_AARCH64="$BIN/cosmo-clang"
TARGET_X86_64="--target=x86_64"
TARGET_AARCH64="--target=aarch64"
FPORTCOSMO=
FNO_INLINE_FUNCTIONS_CALLED_ONCE="-fno-inline-functions-called-once"
}
use_gcc
X=
OPT=
ARGS=
FLAGS=
OUTPUT=
NEED_X=
MDFLAG=0
MCOSMO=0
INTENT=ld
NEED_JOIN=
NEED_EQUAL=
NEED_OUTPUT=
APELINKFLAGS=
FLAGS_X86_64=
FLAGS_AARCH64=
INPUT_FILE_COUNT=0
DEPENDENCY_OUTPUT=
NEED_DEPENDENCY_OUTPUT=
for x; do
if [ x"$x" != x"${x#* }" ]; then
fatal_error "arguments containing spaces unsupported: $x"
elif [ -n "$NEED_OUTPUT" ]; then
NEED_OUTPUT=
OUTPUT=$x
continue
elif [ -n "$NEED_DEPENDENCY_OUTPUT" ]; then
NEED_DEPENDENCY_OUTPUT=
DEPENDENCY_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 [ -n "$NEED_X" ]; then
NEED_X=
X=$x
x="-x${x}"
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"-MF" ]; then
NEED_DEPENDENCY_OUTPUT=1
continue
elif [ x"$x" != x"${x#-MF}" ]; then # startswith(x, "-MF")
DEPENDENCY_OUTPUT=${x#-MF}
continue
elif [ x"$x" = x"-MQ" ]; then
NEED_DEPENDENCY_OUTPUT=1
continue
elif [ x"$x" = x"-Wl,--version" ]; then
cat <<EOF
GNU ld (GNU Binutils) 2.42
Copyright (C) 2024 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) a later version.
This program has absolutely no warranty.
EOF
exit
elif [ x"$x" != x"${x#-O}" ]; then # startswith(x, "-O")
OPT=$x
elif [ x"$x" = x"-c" ]; then
if [ x"$INTENT" != x"cpp" ]; then
INTENT=cc
fi
continue
elif [ x"$x" = x"-E" ] ||
[ x"$x" = x"-M" ] ||
[ x"$x" = x"-MM" ]; 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"-mdbg" ]; then
MODE=dbg
continue
elif [ x"$x" = x"-mtiny" ]; then
MODE=tiny
continue
elif [ x"$x" = x"-moptlinux" ]; then
MODE=optlinux
continue
elif [ x"$x" = x"-mclang" ]; then
use_clang
continue
elif [ x"$x" = x"-mgcc" ]; then
use_gcc
continue
elif [ x"$x" = x"-m64" ]; then
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 -fschedule-insns2"
elif [ x"$x" = x"-r" ] ||
[ x"$x" = x"-S" ] ||
[ x"$x" = x"-pie" ] ||
[ x"$x" = x"-shared" ] ||
[ x"$x" = x"-nostdlib" ] ||
[ x"$x" = x"-mred-zone" ] ||
[ 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"-fpie" ] || [ x"$x" = x"-pie" ]; then
# no support for position independent executables
# https://github.com/jart/cosmopolitan/issues/1126
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. cosmocc "-Xx86_64 -msse3 -mavx -mavx2 -mf16c -mfma"
FLAGS_X86_64="$FLAGS_X86_64 ${x#-Xx86_64}"
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"-x" ]; then
NEED_X=1
continue
elif [ x"$x" != x"${x#-x}" ]; then
X=${x#-x}
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"-MF" ] ||
[ x"$x" = x"-MT" ] ||
[ 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
elif [ x"$x" = x"-MD" ] ||
[ x"$x" = x"-MMD" ]; then
MDFLAG=1
fi
FLAGS="$FLAGS $x"
ARGS="$ARGS $x"
done
# precompiled header mode
if [ $INTENT != cpp ]; then
if [ -z "$X" ]; then
ONLY_HEADER_INPUTS=1
for x in $ARGS; do
if [ x"$x" = x"${x#-*}" ] && # !startswith(x, "-")
[ x"$x" = x"${x%.h}" ] && # !endswith(x, ".h")
[ x"$x" = x"${x%.hpp}" ]; then # !endswith(x, ".hpp")
ONLY_HEADER_INPUTS=0
break
fi
done
if [ $ONLY_HEADER_INPUTS -eq 1 ]; then
INTENT=gch
fi
elif [ x"$X" = x"c-header" ] ||
[ x"$X" = x"c++-header" ]; then
INTENT=gch
fi
fi
if [ $INTENT = gch ]; then
fatal_error "precompiled headers only supported with ARCH-unknown-cosmo-cc compilers"
fi
# check for incorrect usage
if [ $INPUT_FILE_COUNT -eq 0 ]; then
fatal_error "no input files"
elif [ -n "$OUTPUT" ] && [ $INPUT_FILE_COUNT -gt 1 ]; then
if [ $INTENT = cc ] || [ $INTENT = cpp ]; then
fatal_error "cannot specify '-o' with '-c' or '-E' with multiple files"
fi
fi
if [ $INTENT = ld ]; then
use_gcc
fi
PLATFORM="-D__COSMOPOLITAN__ -D__COSMOCC__ -D__FATCOSMOCC__"
PREDEF="-include libc/integral/normalize.inc"
CPPFLAGS="-fno-pie -nostdinc -isystem $BIN/../include"
CFLAGS="$FPORTCOSMO -fno-semantic-interposition"
LDFLAGS="-static -nostdlib -no-pie -fuse-ld=bfd -Wl,-z,noexecstack -Wl,-z,norelro -Wl,--gc-sections"
PRECIOUS="-fno-omit-frame-pointer"
# these features screw with backtraces so avoid them
if [ x"$OPT" != x"-Os" ] && [ x"$MODE" != x"tiny" ] && [ x"$MODE" != x"optlinux" ]; then
CFLAGS="$CFLAGS -fno-optimize-sibling-calls -mno-omit-leaf-frame-pointer"
fi
if [ x"$OPT" != x"-O3" ] && [ x"$MODE" != x"optlinux" ]; then
if [ $CLANG -eq 0 ]; then
CFLAGS="$CFLAGS -fno-schedule-insns2"
fi
fi
if [ x"$X" = x"c" ] || [ x"$X" = x"c-header" ]; then
CPLUSPLUS=0
elif [ x"$X" = x"c++" ] || [ x"$X" = x"c++-header" ]; then
CPLUSPLUS=1
elif [ x"$PROG" != x"${PROG%++}" ]; then
CPLUSPLUS=1
else
CPLUSPLUS=0
fi
if [ $CPLUSPLUS -eq 1 ]; then
CC_X86_64=$CXX_X86_64
CC_AARCH64=$CXX_AARCH64
CPPFLAGS="-isystem $BIN/../include/third_party/libcxx $CPPFLAGS"
else
CFLAGS="$CFLAGS -Wno-implicit-int"
fi
if [ x"$MODE" = x"dbg" ]; then
LIB_X86_64="$BIN/../x86_64-linux-cosmo/lib/dbg"
LIB_AARCH64="$BIN/../aarch64-linux-cosmo/lib/dbg"
elif [ x"$MODE" = x"tiny" ]; then
LIB_X86_64="$BIN/../x86_64-linux-cosmo/lib/tiny"
LIB_AARCH64="$BIN/../aarch64-linux-cosmo/lib/tiny"
elif [ x"$MODE" = x"optlinux" ]; then
LIB_X86_64="$BIN/../x86_64-linux-cosmo/lib/optlinux"
LIB_AARCH64="$BIN/../aarch64-linux-cosmo/lib/optlinux"
else
LIB_X86_64="$BIN/../x86_64-linux-cosmo/lib"
LIB_AARCH64="$BIN/../aarch64-linux-cosmo/lib"
fi
CRT_X86_64="$LIB_X86_64/ape.o $LIB_X86_64/crt.o"
CPPFLAGS_X86_64="$CPPFLAGS"
CFLAGS_X86_64="$CFLAGS -mno-tls-direct-seg-refs"
LDFLAGS_X86_64="$LDFLAGS -L$LIB_X86_64 -L$BIN/../x86_64-linux-cosmo/lib -Wl,-T,$LIB_X86_64/ape.lds -Wl,-z,common-page-size=4096 -Wl,-z,max-page-size=16384"
LDLIBS_X86_64="-lcosmo"
CRT_AARCH64="$LIB_AARCH64/crt.o"
CPPFLAGS_AARCH64="$CPPFLAGS -fsigned-char"
CFLAGS_AARCH64="$CFLAGS -ffixed-x18 -ffixed-x28"
LDFLAGS_AARCH64="$LDFLAGS -L$LIB_AARCH64 -L$BIN/../aarch64-linux-cosmo/lib -Wl,-T,$LIB_AARCH64/aarch64.lds -Wl,-z,common-page-size=16384 -Wl,-z,max-page-size=16384"
LDLIBS_AARCH64="-lcosmo"
SUPPORT_VECTOR=-1
if [ x"$MODE" = x"optlinux" ]; then
CPPFLAGS_X86_64="$CPPFLAGS_X86_64 -mno-red-zone"
SUPPORT_VECTOR=linux
fi
if [ x"$OPT" != x"-Os" ] && [ x"$MODE" != x"tiny" ] && [ x"$MODE" != x"optlinux" ]; then
CFLAGS_X86_64="${CFLAGS_X86_64} -fpatchable-function-entry=18,16 $FNO_INLINE_FUNCTIONS_CALLED_ONCE -DFTRACE -DSYSDEBUG"
CFLAGS_AARCH64="${CFLAGS_AARCH64} -fpatchable-function-entry=7,6 $FNO_INLINE_FUNCTIONS_CALLED_ONCE -DFTRACE -DSYSDEBUG"
fi
if [ $CPLUSPLUS -eq 1 ]; then
LDLIBS_X86_64="-lcxx ${LDLIBS_X86_64}"
LDLIBS_AARCH64="-lcxx ${LDLIBS_AARCH64}"
fi
if [ $MCOSMO -eq 1 ]; then
CPPFLAGS_X86_64="${CPPFLAGS_X86_64} -D_COSMO_SOURCE"
CPPFLAGS_AARCH64="${CPPFLAGS_AARCH64} -D_COSMO_SOURCE"
fi
log_original
if [ $INTENT = cpp ]; then
if [ -n "$OUTPUT" ]; then
ARGS="$ARGS -o$OUTPUT"
fi
# undefine cpu-specific and linux-specific defines
# we get rid of long double too to not lead astray
# we shall leave behind unix, __unix, and __unix__
set -- \
"$CC_X86_64" \
-U__k8 \
-U__k8__ \
-U__amd64 \
-U__amd64__ \
-U__x86_64 \
-U__x86_64__ \
-U__MMX__ \
-U__MMX_WITH_SSE__ \
-U__SSE_MATH__ \
-U__SEG_FS \
-U__SEG_GS \
-U__SSE__ \
-U__FXSR__ \
-U__SSE2__ \
-U__SSE2_MATH__ \
-Ulinux \
-U__linux \
-U__linux__ \
-U__gnu_linux__ \
-mno-red-zone \
-mlong-double-64 \
$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"
}
get_dependency_outputs() {
if [ $MDFLAG -eq 1 ]; then
if [ -n "$DEPENDENCY_OUTPUT" ]; then
DEPENDENCY_FLAGS_x86_64="-MF $DEPENDENCY_OUTPUT"
mangle_object_path "$DEPENDENCY_OUTPUT" aarch64
DEPENDENCY_FLAGS_AARCH64="-MF $mangled_path"
else
base="$1.d"
DEPENDENCY_FLAGS_x86_64="-MF $base"
mangle_object_path "$base" aarch64
DEPENDENCY_FLAGS_AARCH64="-MF $mangled_path"
fi
fi
}
mktemper() {
"$BIN/mktemper" \
"$TMPDIR/fatcosmocc.XXXXXXXXXXXXX$1"
}
build_object() {
out2=$(mktemper .txt) || Exit
TEMP_FILES="${TEMP_FILES} $out2"
(
set -- \
"$CC_X86_64" \
$TARGET_X86_64 \
-o"$OUTPUT_X86_64" \
$PLATFORM \
$PREDEF \
$CFLAGS_X86_64 \
$CPPFLAGS_X86_64 \
"$@" \
$DEPENDENCY_FLAGS_x86_64 \
$FLAGS_X86_64 \
$PRECIOUS
log_command "$@"
"$@" || exit
set -- \
"$BIN/fixupobj" \
"$OUTPUT_X86_64"
log_command "$@"
exec "$@"
) &
pid1=$!
(
set -- \
"$CC_AARCH64" \
$TARGET_AARCH64 \
-o"$OUTPUT_AARCH64" \
$PLATFORM \
$PREDEF \
$CFLAGS_AARCH64 \
$CPPFLAGS_AARCH64 \
"$@" \
$DEPENDENCY_FLAGS_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"
get_dependency_outputs "$OUTPUT"
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"
get_dependency_outputs "${o%.*}"
build_object $FLAGS -c "$x"
fi
else
# e.g. `cc foo.c` should build a.out
if [ -z "$OUTPUT" ]; then
OUTPUT=a.out
fi
if [ -z "$DEPENDENCY_OUTPUT" ]; then
o=${x##*/}
DEPENDENCY_OUTPUT="a-${o%.*}.d"
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}"
get_dependency_outputs
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" \
$TARGET_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" \
$TARGET_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" \
-V "$SUPPORT_VECTOR" \
-l "$BIN/ape-x86_64.elf" \
-l "$BIN/ape-aarch64.elf" \
-M "$BIN/ape-m1.c" \
-o "$OUTPUT" \
$APELINKFLAGS \
"$OUTPUT_X86_64" \
"$OUTPUT_AARCH64"
log_command "$@"
"$@" || Exit
if [ x"$MODE" != "optlinux" ]; then
set -- \
"$BIN/pecheck" "$OUTPUT"
log_command "$@"
"$@" || Exit
fi
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