#!/bin/sh

set -e

JOBS="$1"
TARGET="$2" # Example: riscv64-linux-gnu
MCPU="$3" # Examples: `baseline`, `native`, `generic+v7a`, or `arm1176jzf_s`

ROOTDIR="$(pwd)"

TARGET_OS_AND_ABI=${TARGET#*-} # Example: linux-gnu
TARGET_OS_LOWER=${TARGET_OS_AND_ABI%-*} # Example: linux
TARGET_OS_CMAKE=${TARGET_OS_LOWER^} # Example: Linux

# First build the libraries for Zig to link against, as well as native `llvm-tblgen`.
mkdir -p "$ROOTDIR/out/build-llvm-host"
cd "$ROOTDIR/out/build-llvm-host"
cmake "$ROOTDIR/llvm" \
  -DLLVM_ENABLE_PROJECTS="lld;clang" \
  -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD="AVR" \
  -DLLVM_ENABLE_LIBXML2=OFF \
  -DCMAKE_INSTALL_PREFIX="$ROOTDIR/out/host" \
  -DCMAKE_PREFIX_PATH="$ROOTDIR/out/host" \
  -DLLVM_INCLUDE_TESTS=OFF \
  -DLLVM_INCLUDE_GO_TESTS=OFF \
  -DLLVM_INCLUDE_EXAMPLES=OFF \
  -DLLVM_INCLUDE_BENCHMARKS=OFF \
  -DLLVM_ENABLE_BINDINGS=OFF \
  -DLLVM_ENABLE_OCAMLDOC=OFF \
  -DLLVM_ENABLE_Z3_SOLVER=OFF \
  -DCLANG_BUILD_TOOLS=OFF \
  -DCMAKE_BUILD_TYPE=Release
make "$JOBS" install

# Now we build Zig, still with system C/C++ compiler, linking against LLVM,
# Clang, LLD we just built from source.
mkdir -p "$ROOTDIR/out/build-zig-host"
cd "$ROOTDIR/out/build-zig-host"
cmake "$ROOTDIR/zig" -DCMAKE_INSTALL_PREFIX="$ROOTDIR/out/host" -DCMAKE_PREFIX_PATH="$ROOTDIR/out/host" -DCMAKE_BUILD_TYPE=Release
make "$JOBS" install

# Now we have Zig as a cross compiler
ZIG="$ROOTDIR/out/host/bin/zig"
export CC="$ZIG cc -target $TARGET -mcpu=$MCPU"
export CXX="$ZIG c++ -target $TARGET -mcpu=$MCPU"

# Rebuild LLVM with Zig.
mkdir -p "$ROOTDIR/out/build-llvm-$TARGET"
cd "$ROOTDIR/out/build-llvm-$TARGET"
cmake "$ROOTDIR/llvm" \
  -DLLVM_ENABLE_PROJECTS="lld;clang" \
  -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD="AVR" \
  -DLLVM_ENABLE_LIBXML2=OFF \
  -DCMAKE_INSTALL_PREFIX="$ROOTDIR/out/$TARGET" \
  -DCMAKE_PREFIX_PATH="$ROOTDIR/out/$TARGET" \
  -DCMAKE_BUILD_TYPE=Release \
  -DCMAKE_CROSSCOMPILING=True \
  -DCMAKE_SYSTEM_NAME="$TARGET_OS_CMAKE" \
  -DCMAKE_AR="$ROOTDIR/out/host/bin/llvm-ar" \
  -DCMAKE_RANLIB="$ROOTDIR/out/host/bin/llvm-ranlib" \
  -DLLVM_TABLEGEN="$ROOTDIR/out/host/bin/llvm-tblgen" \
  -DCLANG_TABLEGEN="$ROOTDIR/out/build-llvm-host/bin/clang-tblgen" \
  -DLLVM_BUILD_TOOLS=OFF \
  -DLLVM_INCLUDE_UTILS=OFF \
  -DLLVM_INCLUDE_TESTS=OFF \
  -DLLVM_INCLUDE_GO_TESTS=OFF \
  -DLLVM_INCLUDE_EXAMPLES=OFF \
  -DLLVM_INCLUDE_BENCHMARKS=OFF \
  -DLLVM_ENABLE_BINDINGS=OFF \
  -DLLVM_ENABLE_OCAMLDOC=OFF \
  -DLLVM_ENABLE_Z3_SOLVER=OFF \
  -DCLANG_BUILD_TOOLS=OFF \
  -DCLANG_ENABLE_ARCMT=OFF \
  -DLLVM_BUILD_STATIC=ON \
  -DLIBCLANG_BUILD_STATIC=ON \
  -DLLVM_DEFAULT_TARGET_TRIPLE="$TARGET"
cd "$ROOTDIR/out/build-llvm-$TARGET/tools/lld"
make "$JOBS" install
cd "$ROOTDIR/out/build-llvm-$TARGET/tools/clang/lib"
make "$JOBS" install
cd "$ROOTDIR/out/build-llvm-$TARGET/lib"
make "$JOBS" install
cd "$ROOTDIR/out/build-llvm-$TARGET"
make "$JOBS" install-llvm-headers install-clang-headers install-LLVMSupport install-LLVMDemangle

# Finally, we can cross compile Zig itself, with Zig.
mkdir -p "$ROOTDIR/out/build-zig-$TARGET"
cd "$ROOTDIR/out/build-zig-$TARGET"
cmake "$ROOTDIR/zig" \
  -DCMAKE_INSTALL_PREFIX="$ROOTDIR/out/zig-$TARGET-$MCPU" \
  -DCMAKE_PREFIX_PATH="$ROOTDIR/out/$TARGET" \
  -DCMAKE_CROSSCOMPILING=True \
  -DCMAKE_SYSTEM_NAME="$TARGET_OS_CMAKE" \
  -DCMAKE_AR="$ROOTDIR/out/host/bin/llvm-ar" \
  -DCMAKE_RANLIB="$ROOTDIR/out/host/bin/llvm-ranlib" \
  -DCMAKE_BUILD_TYPE=Release \
  -DZIG_TARGET_TRIPLE="$TARGET" \
  -DZIG_TARGET_MCPU="$MCPU" \
  -DZIG_EXECUTABLE="$ZIG"
make "$JOBS" install
