#!/bin/sh
set -eu

toolchain_dir=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
config="$toolchain_dir/compiler.conf"

if [ ! -r "$config" ]; then
    printf '%s\n' "missing cross-compiler configuration: $config" >&2
    exit 1
fi

{
    IFS= read -r c_compiler
    IFS= read -r cxx_compiler
    IFS= read -r sysroot
    IFS= read -r linker
    IFS= read -r builtins
    IFS= read -r rust_eh_personality
    IFS= read -r target
} <"$config"

cxx_runtime=no
case "${0##*/}" in
    *-cc)
        compiler=$c_compiler
        ;;
    *-bootstrap-c++)
        compiler=$cxx_compiler
        ;;
    *-c++)
        compiler=$cxx_compiler
        cxx_runtime=yes
        set -- \
            -nostdinc++ \
            -isystem "$sysroot/usr/include/c++/v1" \
            "$@"
        ;;
    *)
        printf '%s\n' "cross compiler invoked with an unknown name: ${0##*/}" >&2
        exit 1
        ;;
esac

link=executable
caller_startup=no
for argument do
    case "$argument" in
        -c|-E|-M|-MM|-S|-fsyntax-only)
            link=compile
            ;;
        -shared)
            link=shared
            ;;
        -r)
            link=relocatable
            ;;
        -nostartfiles)
            caller_startup=yes
            ;;
    esac
done

if [ "$link" = compile ]; then
    exec "$compiler" \
        --target="$target" \
        --sysroot="$sysroot" \
        "$@"
fi

# Shared and relocatable links still need the target linker, but Clang should
# select their startup objects and libraries because they are not base-system
# executables and must not inherit the static base link recipe below.
if [ "$link" = shared ] || [ "$link" = relocatable ]; then
    exec "$compiler" \
        --target="$target" \
        --sysroot="$sysroot" \
        --ld-path="$linker" \
        "$@"
fi

# Rust's self-contained musl target passes its own CRT objects together with
# -nostartfiles, so the caller supplies everything needed for startup.
if [ "$caller_startup" = yes ]; then
    exec "$compiler" \
        --target="$target" \
        --sysroot="$sysroot" \
        --ld-path="$linker" \
        -nostdlib \
        -static \
        -L"$sysroot/usr/lib" \
        "$@" \
        -Wl,--start-group \
        ${MOUSE_CROSS_EXTRA_STATIC_LIBS:-} \
        "$builtins" \
        "$sysroot/usr/lib/libc.a" \
        -Wl,--end-group
fi

if [ "$cxx_runtime" = yes ]; then
    exec "$compiler" \
        --target="$target" \
        --sysroot="$sysroot" \
        --ld-path="$linker" \
        -nostdlib \
        -static \
        "$sysroot/usr/lib/crt1.o" \
        "$sysroot/usr/lib/crti.o" \
        -L"$sysroot/usr/lib" \
        "$@" \
        -Wl,--start-group \
        ${MOUSE_CROSS_EXTRA_STATIC_LIBS:-} \
        "$sysroot/usr/lib/libc++.a" \
        "$sysroot/usr/lib/libc++abi.a" \
        "$sysroot/usr/lib/libunwind.a" \
        "$builtins" \
        "$rust_eh_personality" \
        "$sysroot/usr/lib/libc.a" \
        -Wl,--end-group \
        "$sysroot/usr/lib/crtn.o"
fi

exec "$compiler" \
    --target="$target" \
    --sysroot="$sysroot" \
    --ld-path="$linker" \
    -nostdlib \
    -static \
    "$sysroot/usr/lib/crt1.o" \
    "$sysroot/usr/lib/crti.o" \
    -L"$sysroot/usr/lib" \
    "$@" \
    -Wl,--start-group \
    ${MOUSE_CROSS_EXTRA_STATIC_LIBS:-} \
    "$builtins" \
    "$rust_eh_personality" \
    "$sysroot/usr/lib/libc.a" \
    -Wl,--end-group \
    "$sysroot/usr/lib/crtn.o"
