#!/bin/bash
[% c("var/set_default_env") -%]
distdir=/var/tmp/dist/[% project %]
mkdir -p $distdir
tar -C /var/tmp/dist -xf [% c('input_files_by_name/cmake') %]
export PATH="/var/tmp/dist/cmake/bin:$PATH"
tar -C /var/tmp/dist -xf [% c('input_files_by_name/ninja') %]
export PATH=/var/tmp/dist/ninja:$PATH
tar -C /var/tmp/dist -xf [% c('input_files_by_name/rust_prebuilt') %]
cd /var/tmp/dist/rust-[% c('version') %]-x86_64-unknown-linux-gnu
./install.sh --prefix=$distdir-rust-prebuilt
export PATH="$distdir-rust-prebuilt/bin:$PATH"

[% pc(c('var/compiler'), 'var/setup', { compiler_tarfile => c('input_files_by_name/' _ c('var/compiler')) }) %]
[% IF c("var/linux") || c("var/android") -%]
  # See the config file for more details on why we do that also on Windows
  tar -C /var/tmp/dist -xf $rootdir/[% c('input_files_by_name/clang') %]
  export PATH=/var/tmp/dist/clang/bin:$PATH
[% END -%]
[% IF c("var/linux") -%]
  [% pc('python', 'var/setup', { python_tarfile => c('input_files_by_name/python') }) %]
  export LLVM_CONFIG="/var/tmp/dist/clang/bin/llvm-config"
  export CC=clang
  export CXX=clang++
  export CFLAGS='--gcc-toolchain=/var/tmp/dist/gcc'
  export CXXFLAGS='--gcc-toolchain=/var/tmp/dist/gcc'
  export RUSTFLAGS="-L/var/tmp/dist/gcc/lib64"
[% ELSIF c("var/macos") -%]
  # We need to clear `CC` and `LDFLAGS` as they are used for the host platform
  # (i.e. Linux).
  unset CC
  unset LDFLAGS

  mkdir $distdir/helper
  # We need to adapt our CFLAGS and make sure our flags are passed down to all
  # dependencies. Using `CFLAGS_x86_apple-darwin` did not do the trick, so resort
  # to a wrapper script.
  cat > $distdir/helper/[% c("var/build_target") %]-clang << 'EOF'
#!/bin/sh
BASEDIR=/var/tmp/dist/macosx-toolchain
$BASEDIR/cctools/bin/[% c("var/build_target") %]-clang -target [% c("var/build_target") %] -B $BASEDIR/cctools/bin -isysroot $sysrootdir -Wl,-syslibroot,$sysrootdir -Wl,-dead_strip -Wl,-pie [% IF c('var/macos-aarch64') %]-mcpu=apple-m1[% END %] "$@"
EOF

  chmod +x $distdir/helper/[% c("var/build_target") %]-clang
  export PATH=$distdir/helper:$PATH
[% ELSIF c("var/windows") -%]
  pushd /var/tmp/dist/mingw-w64-clang/bin
  ln -s clang cc
  ln -s clang++ c++
  popd
[% END -%]

cd $rootdir
mkdir -p /var/tmp/build
tar -C /var/tmp/build -xf  [% c('input_files_by_name/rust') %]
cd /var/tmp/build/rustc-[% c('version') %]-src

[% IF c("var/windows") -%]
  patch -p1 < $rootdir/chkstk.patch
  sed -i 's/117b50d6725ee0af0a7b3d197ea580655561f66a870ebc450d96af22bf7f39f6/1eebe6e65b11cae356e3c19a886d7585d3cfed41899b5387209516d957613032/g' vendor/compiler_builtins/.cargo-checksum.json
[% END -%]

# This is a workaround to get access to the libunwind header files. Our LLVM_CONFIG
# thinks that the llvm source root is at /var/tmp/dist/clang-source because that's
# where it was when clang was compiled.
ln -s "/var/tmp/build/rustc-[% c('version') %]-src/src/llvm-project" "/var/tmp/build/clang-source"

mkdir build
cd build

# We use
# `--enable-local-rust` to avoid downloading the required compiler during build
# time
# `--enable-vendor` to avoid downloading crates during build time and just use
# the ones which are shipped with the source
#
# `--enable-extended` to build not only rustc but cargo as well
#
# `--release-channel=stable` to just include stable features in the compiler
#
# `--sysconfdir=etc` to avoid install failures as |make install| wants to write
# to /etc otherwise
#
# `--llvm-root=$llvm_root` to avoid building LLVM again while building Rust
#
# `--target`: x86-64 Linux and WASM are always enabled. Additional targets are
# enabled on the configuration file.
#
# --set rust.jemalloc to use jemalloc. This option is used also in the prebuilt
# binaries, and we added it because when we were using Debian Jessie, the build
# never ended without this option (see tor-browser-build#40591)
#
# the `target` triple to explicitly specify the architecture and platform
# for the compiler/std lib. Ideally, it should not be needed unless one is
# cross-compiling, but compiling `alloc_jemalloc` fails without that in a
# 32bit container. "--host=x86_64-unknown-linux-gnu" is used in its
# configure script in this case.
#
# Finally, we tell Rust to use some tools from LLVM, like the prebuilt
# binaries do.

../configure \
  --prefix=$distdir \
  --disable-docs --disable-compiler-docs \
  --enable-local-rust \
  --enable-vendor \
  --enable-extended \
  --release-channel=stable \
  --sysconfdir=etc \
  --llvm-root=[% c('var/llvm_root') %] \
  --set rust.jemalloc \
  --target=x86_64-unknown-linux-gnu,wasm32-unknown-unknown,[% c("var/target") %] \
  --set target.x86_64-unknown-linux-gnu.linker=clang \
  --set target.x86_64-unknown-linux-gnu.ar=llvm-ar \
  --set target.x86_64-unknown-linux-gnu.ranlib=llvm-ranlib \
  --set target.wasm32-unknown-unknown.linker=clang \
  --set target.wasm32-unknown-unknown.ar=llvm-ar \
  --set target.wasm32-unknown-unknown.ranlib=llvm-ranlib \
  --set rust.lld=true \
  [% c("var/target_flags") %]

make -j[% c("num_procs") %]
make install
cd /var/tmp/dist

[% IF c("var/linux") -%]
  # When we compile some Rust-only projects such as cbindgen, we do not include
  # the C/C++ compilers and their modern libstdc++ library.
  # For simplicity, we keep it also with Rust, and add it to LD_LIBRARY_PATH
  # if needed.
  cp gcc/lib64/libstdc++.so* rust/lib/
[% END -%]

[% c('tar', {
        tar_src => [ project ],
        tar_args => '-caf ' _ dest_dir _ '/' _ c('filename'),
        }) %]
