# Maintainer: Johannes Löthberg <johannes@kyriasis.com>
# Maintainer: Jan Alexander Steffens (heftig) <heftig@archlinux.org>
# Contributor: Alexander F Rødseth <xyproto@archlinux.org>
# Contributor: Daniel Micay <danielmicay@gmail.com>
# Contributor: userwithuid <userwithuid@gmail.com>

pkgbase=rust
pkgname=(
  rust
  rust-musl
  rust-src
  rust-wasm

  # x86_64 only
  lib32-rust-libs

  # cross targets
  rust-aarch64-gnu
  rust-aarch64-musl
)
pkgver=1.95.0
pkgrel=1
epoch=1
pkgdesc="Systems programming language focused on safety, speed and concurrency"
url=https://www.rust-lang.org/
arch=(
  aarch64
  loong64
  riscv64
  x86_64
)
license=("Apache-2.0 OR MIT")
depends=(
  bash
  compiler-rt
  curl
  gcc
  glibc
  libgcc
  libgit2
  libssh2
  libstdc++
  lld
  llvm-libs
  openssl
  zlib
)
makedepends=(
  clang
  cmake
  libffi
  llvm
  musl
  ninja
  perl
  python
  rust
  wasi-libc
  wasm-component-ld
)
makedepends_loong64=(
  aarch64-linux-gnu-gcc
  aarch64-linux-gnu-glibc
  musl-aarch64
  musl-x86_64
)
makedepends_riscv64=(
  aarch64-linux-gnu-gcc
  aarch64-linux-gnu-glibc
  musl-aarch64
  musl-x86_64
)
makedepends_x86_64=(
  aarch64-linux-gnu-gcc
  aarch64-linux-gnu-glibc
  lib32-gcc-libs
  lib32-glibc
  musl-aarch64
)
checkdepends=(
  gdb
  procps-ng
)
options=(
  !emptydirs
  !lto
)
source=(
  "https://static.rust-lang.org/dist/rustc-$pkgver-src.tar.xz"{,.asc}

  # Patch bootstrap so that rust-analyzer-proc-macro-srv
  # is in /usr/lib instead of /usr/libexec
  0001-bootstrap-Change-libexec-dir.patch

  # Put bash completions where they belong
  0002-bootstrap-Change-bash-completion-dir.patch

  # Fix build with system rustc
  # https://github.com/rust-lang/rust/issues/143735
  0003-bootstrap-Workaround-for-system-stage0.patch

  # Use our *-pc-linux-gnu targets, making LTO with clang simpler
  0004-compiler-Change-LLVM-targets.patch

  # Use our ld.lld
  0005-compiler-Use-ld.lld-by-default.patch

  # Use our target-specific GCCs, like aarch64-linux-gnu-gcc
  0006-compiler-Use-target-specific-GCC-linkers.patch

  # Make the riscv64 musl target behave like the x86_64 musl target
  0007-compiler-Link-riscv64-musl-statically.patch

  # Prefer "lib" over "lib64"
  0008-compiler-Swap-primary-and-secondary-lib-dirs.patch
)
source_aarch64=(bootstrap.aarch64.toml)
source_loong64=(bootstrap.loong64.toml)
source_riscv64=(bootstrap.riscv64.toml)
source_x86_64=(bootstrap.x86_64.toml)
b2sums=('0f255678231df79c9910cf5d9efbd762d1955ad78512194e3e06b3cec327f346bc98c526d2a8468ea53f57132c9765a134fe203267c1f6696e6719db820f342a'
        'SKIP'
        '7ce67f342423aca0de86dac7d51ed8048ffa9fbfea356c50aa043bbfdc80ba4de95c236c2eb0842e94562a934715636dd0bb6f6c48e71217e7327a70f380589a'
        'a05cea3b3c3f62e7a96fb38e13264d986a39d7da44ebf4123089a75218a83e919a89d1465159e915b24a3110c3d59d2e115f5a1f9f1d59840b5aaabd3c16d5b9'
        'd310f26b37aba3d2c077eacd36d425762d8bf74a6ff07d85dc1dfa5e9497548651b340de01a76f2b2280e09f131a2f5a5be7e52b302754f5c151cf1a3f9c52f0'
        '3412340c4f3db46a80f942ae8e2277d35f7574f1d920ff1024b509596b3769c5f40fdbad57e7d00e5fdd0a379ddead658af2856250cc3f1bfc145db5b5782489'
        '218b0c935887c070eadc1a15a5d5afde01302ef7b85b2c78c26209d50d0a06f10807dd5ddcc0eb355f07c7200b6167dd69f78ae0c278d834d7d04c728edc5db3'
        '8015b14bd00f412c0935961fce5f9671fe3d51256a70eacbf61573c4c8ae35f3cd81372681fe406395ca571363e9f9a9c5b40969e79513f22d808e677a841ae7'
        '6e473abbda7e77fb399b1b5ff0a50efa6b324a4b9f8e0904a0ebca1258e9a84be840465ef1ad716d968fbb580e7bb77d4af2f7dbbbad258749eb9025a7cbc899'
        '127c511718cf15cb3bfd0011c08838f16f073249ed928c37e106eb06e34d4a9c54a7b55b3768381edea72d1f5339c7fd25bdd6477f9d88d693a1ddeeda1006ad')
b2sums_aarch64=('0a2c2c5c4ddadbfe269b4acd5ed0028e01f78c266e56de30010a6706a619e23db14e5f7578fc7b5974832fe48ccb2b5827c268c9c79bccd6ffa057f61ca52c86')
b2sums_loong64=('ca71cf8438d9a5cb898ffa176b99ef059ff0b62805bedce66c3f36dd20cd6be21e0d6bca7e765b717bdbb4a550404c75e64e0af7139bdb3dd98c3b281969de97')
b2sums_riscv64=('b2809d686b4301f755d0769d9edc4a8427d9aab0a74024254848315c7a5abb5f2ec06b33deb7f2a7b72035a4cf08efd313d42aec304ad852598580ba72a17003')
b2sums_x86_64=('6310635b44227fe5ab6a9a70dd7d2b520d223624d1b9069723ef914b7feb8920186099ce77fe903fc089583bbeba8df7ae97d26030c37d6337689133ac726f08')
validpgpkeys=(
  108F66205EAEB0AAA8DD5E1C85AB96E6FA1BE5FE  # Rust Language (Tag and Release Signing Key) <rust-key@rust-lang.org>
)

# Make sure the duplication in rust-wasm is found
COMPRESSZST+=(--long)

prepare() {
  cd rustc-$pkgver-src

  local src
  for src in "${source[@]}"; do
    src="${src%%::*}"
    src="${src##*/}"
    src="${src%.zst}"
    [[ $src = *.patch ]] || continue
    echo "Applying patch $src..."
    patch -Np1 < "../$src"
  done

  local clangdir
  clangdir="$(clang -print-resource-dir)"
  sed -e "s|%description%|Arch Linux $pkgbase $epoch:$pkgver-$pkgrel|g" \
      -e "s|%clangdir%|$clangdir|g" \
      "$srcdir/bootstrap.${CARCH}.toml" > bootstrap.toml
}

_pick() {
  local p="$1" f d; shift
  for f; do
    d="$srcdir/$p/${f#$pkgdir/}"
    mkdir -p "$(dirname "$d")"
    mv "$f" "$d"
    rmdir -p --ignore-fail-on-non-empty "$(dirname "$f")"
  done
}

build() {
  cd rustc-$pkgver-src

  export LIBGIT2_NO_VENDOR=1
  export LIBSSH2_SYS_USE_PKG_CONFIG=1
  export RUST_BACKTRACE=1
  unset CFLAGS CXXFLAGS LDFLAGS

  local xpy_options=(
    -j "$(nproc)"
  )

  local host_tuple do_pgo=0
  case $CARCH in
    aarch64|x86_64) host_tuple=$CARCH-unknown-linux-gnu; do_pgo=1 ;;
    loong64) host_tuple=loongarch64-unknown-linux-gnu ;;
    riscv64) host_tuple=riscv64gc-unknown-linux-gnu ;;
    *) host_tuple=$CARCH-unknown-linux-gnu ;;
  esac

  if (( do_pgo )); then
    local profraw="$PWD/build/profiles"
    mkdir -p "$profraw"

    echo "Building instrumented compiler..."
    python ./x.py build sysroot "${xpy_options[@]}" \
      --rust-profile-generate="$profraw"

    # Building cargo is our workload for profiling
    echo "Profiling instrumented compiler..."
    local stage2="$PWD/build/$host_tuple/stage2"
    LLVM_PROFILE_FILE="$profraw/default_%m_%p.profraw" \
      LD_LIBRARY_PATH="$stage2/lib" RUSTC="$stage2/bin/rustc" \
      cargo build --manifest-path=src/tools/cargo/Cargo.toml

    # Merge the profile data
    local profdata="$PWD/build/rustc.profdata"
    llvm-profdata merge -o "$profdata" "$profraw"

    stat -c "Profile data found (%s bytes)" "$profdata"
    test -s "$profdata"

    # Clean up profraw and instrumented stage2 artifacts
    echo "Removing instrumented compiler..."
    rm -r "$profraw" "$stage2"*/

    xpy_options+=(--rust-profile-use="$profdata")
  fi

  echo "Building optimized compiler..."
  DESTDIR="$srcdir/dest-rust" python ./x.py install "${xpy_options[@]}"

  cd ../dest-rust

  # delete unnecessary files, e.g. files only used for the uninstall script
  rm -v etc/target-spec-json-schema.json
  rm -v usr/lib/rustlib/{components,install.log,rust-installer-version,uninstall.sh}
  rm -v usr/lib/rustlib/manifest-*

  # licenses for main rust package
  local ldir="usr/share/licenses/rust" f d
  mkdir -p "$ldir"
  for f in usr/share/doc/*/{COPYRIGHT,LICENSE}*; do
    d="$(dirname "$f")"
    case $f in
      */LICENSE-APACHE) rm -v "$f" ;;
      *) mv -v "$f" "$ldir/${f##*/}.${d##*/}" ;;
    esac
    rmdir -p --ignore-fail-on-non-empty "$d"
  done

  # rustbuild always installs copies of the shared libraries to /usr/lib,
  # overwrite them with symlinks to the per-architecture versions
  ln -srvft usr/lib usr/lib/rustlib/$host_tuple/lib/*.so

  # Symlink the "self-contained" linker to our system lld
  mkdir -pv usr/lib/rustlib/$host_tuple/bin/gcc-ld
  ln -srvf  usr/bin/lld          usr/lib/rustlib/$host_tuple/bin/rust-lld
  ln -srvf  usr/bin/llvm-objcopy usr/lib/rustlib/$host_tuple/bin/rust-objcopy
  ln -srvft usr/lib/rustlib/$host_tuple/bin/gcc-ld usr/bin/{ld.lld,ld64.lld,lld-link,wasm-ld}

  _pick dest-musl usr/lib/rustlib/${host_tuple/gnu/musl}
  _pick dest-wasm usr/lib/rustlib/wasm32{,v1}-*
  _pick dest-src  usr/lib/rustlib/src

  case $CARCH in
    x86_64)
      _pick dest-i686 usr/lib/rustlib/i686-unknown-linux-gnu
      _pick dest-aarch64-gnu usr/lib/rustlib/aarch64-unknown-linux-gnu
      _pick dest-aarch64-musl usr/lib/rustlib/aarch64-unknown-linux-musl
      ;;
    loong64|riscv64)
      _pick dest-aarch64-gnu usr/lib/rustlib/aarch64-unknown-linux-gnu
      _pick dest-aarch64-musl usr/lib/rustlib/aarch64-unknown-linux-musl
      ;;
  esac
}

_install_licenses() {
  install -Dt "$pkgdir/usr/share/licenses/$pkgname" -m644 \
    rustc-$pkgver-src/{COPYRIGHT,LICENSE-MIT}
}

package_rust() {
  depends+=(
    libcurl.so
    libgcc_s.so
    libgit2.so
    libssh2.so
    libssl.so
  )
  optdepends=(
    'gdb: rust-gdb script'
    'lldb: rust-lldb script'
  )
  provides=(
    cargo
    rustfmt
  )
  conflicts=(
    cargo
    'rust-docs<1:1.56.1-3'
    rustfmt
  )
  replaces=(
    cargo
    cargo-tree
    'rust-docs<1:1.56.1-3'
    rustfmt
  )

  cp -a dest-rust/* "$pkgdir"
}

package_rust-musl() {
  pkgdesc="Musl target for Rust"
  depends=(rust)

  cp -a dest-musl/* "$pkgdir"
  _install_licenses
}

package_rust-src() {
  pkgdesc="Source code for the Rust standard library"
  depends=(rust)

  cp -a dest-src/* "$pkgdir"
  _install_licenses
}

package_rust-wasm() {
  pkgdesc="WebAssembly targets for Rust"
  depends=(
    rust
    wasm-component-ld
  )

  cp -a dest-wasm/* "$pkgdir"
  _install_licenses
}

package_lib32-rust-libs() {
  pkgdesc="32-bit target and libraries for Rust"
  arch=(x86_64)
  depends=(
    lib32-gcc-libs
    lib32-glibc
    rust
  )
  provides=(lib32-rust)
  conflicts=(lib32-rust)
  replaces=(lib32-rust)

  cp -a dest-i686/* "$pkgdir"
  _install_licenses

  cd "$pkgdir"
  mkdir -pv usr/lib32
  ln -srvft usr/lib32 usr/lib/rustlib/i686-unknown-linux-gnu/lib/*.so
}

package_rust-aarch64-gnu() {
  pkgdesc="AArch64 GNU target for Rust"
  arch=(
    loong64
    riscv64
    x86_64
  )
  depends=(
    aarch64-linux-gnu-gcc
    aarch64-linux-gnu-glibc
    rust
  )

  cp -a dest-aarch64-gnu/* "$pkgdir"
  _install_licenses
}

package_rust-aarch64-musl() {
  pkgdesc="AArch64 Musl target for Rust"
  arch=(
    loong64
    riscv64
    x86_64
  )
  depends=(
    aarch64-linux-gnu-gcc
    rust
  )

  cp -a dest-aarch64-musl/* "$pkgdir"
  _install_licenses
}

# vim:set ts=2 sw=2 et:
