# Maintainer: Alexey Pavlov <alexpux@gmail.com>
# Contributor: Zion Nimchuk <zionnimchuk@gmail.com>
# Contributor: Mateusz Mikuła <mati865@gmail.com
# Contributor: Philippe Renon <philippe_renon@yahoo.fr>

_bootstrapping=yes
if [[ $MINGW_PACKAGE_PREFIX == *-clang-* ]]; then
  _bootstrapping=no
fi

rust_dist_server=https://static.rust-lang.org/dist
#rust_dist_server=https://dev-static.rust-lang.org/dist/2024-11-25

_realname=rust
pkgbase=mingw-w64-${_realname}
pkgname=("${MINGW_PACKAGE_PREFIX}-${_realname}"
         $([[ ${CARCH} == i686 ]] || echo "${MINGW_PACKAGE_PREFIX}-rust-wasm")
         "${MINGW_PACKAGE_PREFIX}-rust-src")
pkgver=1.83.0
pkgrel=3
pkgdesc="Systems programming language focused on safety, speed and concurrency (mingw-w64)"
arch=('any')
mingw_arch=('mingw32' 'mingw64' 'ucrt64' 'clang64' 'clangarm64')
url="https://www.rust-lang.org/"
msys2_repository_url="https://github.com/rust-lang/rust"
msys2_references=(
  'archlinux: rust'
  "cpe: cpe:/a:rust-lang:rust"
)
license=('spdx:Apache-2.0 AND MIT')
makedepends=("${MINGW_PACKAGE_PREFIX}-cc"
             "${MINGW_PACKAGE_PREFIX}-clang"
             "${MINGW_PACKAGE_PREFIX}-cmake"
             "${MINGW_PACKAGE_PREFIX}-curl"
             "${MINGW_PACKAGE_PREFIX}-libffi"
             "${MINGW_PACKAGE_PREFIX}-libssh2"
             "${MINGW_PACKAGE_PREFIX}-llvm"
             "${MINGW_PACKAGE_PREFIX}-openssl"
             "${MINGW_PACKAGE_PREFIX}-pkgconf"
             "${MINGW_PACKAGE_PREFIX}-python"
             $([[ "$_bootstrapping" == "no" ]] && echo "${MINGW_PACKAGE_PREFIX}-rust")
             $([[ ${CARCH} == i686 ]] || echo "${MINGW_PACKAGE_PREFIX}-wasi-libc ${MINGW_PACKAGE_PREFIX}-wasm-component-ld")
             "${MINGW_PACKAGE_PREFIX}-zstd"
             "${MINGW_PACKAGE_PREFIX}-zlib")
source=("${rust_dist_server}/${_realname}c-${pkgver}-src.tar.gz"{,.asc}
        "psm-0.1.24.tar.gz::https://crates.io/api/v1/crates/psm/0.1.24/download"
        "config.toml"
        "0001-rustc-llvm-fix-libs.patch"
        "0004-compiler-Use-wasm-ld-for-wasm-targets.patch"
        "0008-disable-self-contained-for-gnu-targets.patch"
        "0013-update-psm.patch")
noextract=(${_realname}c-${pkgver}-src.tar.gz)
sha256sums=('722d773bd4eab2d828d7dd35b59f0b017ddf9a97ee2b46c1b7f7fac5c8841c6e'
            'SKIP'
            '200b9ff220857e53e184257720a14553b2f4aa02577d2ed9842d45d4b9654810'
            '832765ebf86dca77ea371decb9937f77dbf3a377cbb2240d9016f2a82d23b363'
            '7cb1773c288ffb1c1e751edc49b1890c84bf9c362742bc5225d19d474edb73a0'
            '56882f1a0f1404c10c7726d6cc37444f2b343e72b969badfcb43760f80db0f32'
            '98bc3f2bd7371a5b8d14fd7b03bf05574e206d1d9e52bcfbe66d71398504da3c'
            '602481687fa580eb426c619f673128702c800e91d4f476fcbaf48b86a7a1b963')
validpgpkeys=('108F66205EAEB0AAA8DD5E1C85AB96E6FA1BE5FE'  # Rust Language (Tag and Release Signing Key) <rust-key@rust-lang.org>
              '474E22316ABF4785A88C6E8EA2C794A986419D8A'  # Tom Stellard <tstellar@redhat.com>
              'B6C8F98282B944E3B0D5C2530FC3042E345AD05D') # Hans Wennborg <hans@chromium.org>

# hack the bootstrap
_stage0date="2022-08-11"
_stage0version="1.63.0"
if [[ $_bootstrapping != "no" && $MINGW_PACKAGE_PREFIX == *-clang-aarch64 ]]; then
  source+=("https://github.com/mati865/rust-gnullvm-builds/releases/download/${_stage0version}-v2/cargo-${_stage0version}-dev-aarch64-pc-windows-gnullvm.tar.xz"
           "https://github.com/mati865/rust-gnullvm-builds/releases/download/${_stage0version}-v2/rust-std-${_stage0version}-dev-aarch64-pc-windows-gnullvm.tar.xz"
           "https://github.com/mati865/rust-gnullvm-builds/releases/download/${_stage0version}-v2/rustc-${_stage0version}-dev-aarch64-pc-windows-gnullvm.tar.xz")
  noextract+=("cargo-${_stage0version}-dev-aarch64-pc-windows-gnullvm.tar.xz"
              "rust-std-${_stage0version}-dev-aarch64-pc-windows-gnullvm.tar.xz"
              "rustc-${_stage0version}-dev-aarch64-pc-windows-gnullvm.tar.xz")
fi

# =========================================== #
#   Helper macros to help make tasks easier   #
apply_patch_with_msg() {
  for _patch in "$@"
  do
    msg2 "Applying ${_patch}"
    patch -Nbp1 -i "${srcdir}/${_patch}"
  done
}
# =========================================== #

prepare() {
  plain "Extracting ${_realname}c-${pkgver}-src.tar.gz"
  tar -xzf ${_realname}c-${pkgver}-src.tar.gz || true

  # use latest version of psm to fix arm4 build
  rm -r ${_realname}c-${pkgver}-src/vendor/psm-0.1.23
  mv psm-0.1.24 ${_realname}c-${pkgver}-src/vendor/psm-0.1.24

  # 0008-disable-self-contained-for-gnu-targets.patch allows self-contained for non-windows-gnu targets
  cd ${_realname}c-${pkgver}-src
  apply_patch_with_msg \
    0001-rustc-llvm-fix-libs.patch \
    0008-disable-self-contained-for-gnu-targets.patch

  apply_patch_with_msg \
    0013-update-psm.patch

  if [[ ${CARCH} != i686 ]]; then
    apply_patch_with_msg \
      0004-compiler-Use-wasm-ld-for-wasm-targets.patch
  fi
}

build() {
  mkdir -p "${MSYSTEM}" && cd "${MSYSTEM}"

  # hack to inject the bootstrap compiler
  if [[ $_bootstrapping != "no" && $MINGW_PACKAGE_PREFIX == *-clang-aarch64 ]]; then
    mkdir -p "build/cache/${_stage0date}/"
    cp -f "${srcdir}/cargo-${_stage0version}-dev-aarch64-pc-windows-gnullvm.tar.xz" \
      "${srcdir}/rust-std-${_stage0version}-dev-aarch64-pc-windows-gnullvm.tar.xz" \
      "${srcdir}/rustc-${_stage0version}-dev-aarch64-pc-windows-gnullvm.tar.xz" \
      "build/cache/${_stage0date}/"
  fi

  if [[ $MINGW_PACKAGE_PREFIX == *-clang-* ]]; then
    # We have to do the following because rust doesn't count x86_64-w64-mingw32 as a target triple
    export OSTYPE="$CARCH-pc-windows-gnullvm"
  else
    # We have to do the following because rust doesn't count x86_64-w64-mingw32 as a target triple
    export OSTYPE="$CARCH-pc-windows-gnu"
  fi

  if [[ $MINGW_PACKAGE_PREFIX != *-clang-aarch64 ]]; then
    local _unsupported_options="-march=nocona -msahf"
    # Remove unsupported options for target wasm32-*
    export CFLAGS="${CFLAGS#$_unsupported_options}"

    # Add options back for target $OSTYPE
    export CFLAGS_${OSTYPE//-/_}="$_unsupported_options"
  fi

  # The rust build uses git if it's available but can't handle cygwin git paths
  # so we try to make git not detect any repo with this
  export GIT_DIR=/dev/null

  # For a faster build:
  # - add --disable-docs and --disable-compiler-docs
  # - compile only rustc by removing --enable-extended
  # - run makepkg-mingw with --nocheck
  # - remove --stage 2

  export RUST_BACKTRACE=1

  # substitute the values in config.toml
  export MSYS2_ENV_CONV_EXCL='INSTALL_PREFIX'
  export INSTALL_PREFIX="${MINGW_PREFIX}"
  export PKGREL="${pkgrel}"
  envsubst < ../config.toml > "../${_realname}c-${pkgver}-src/config.toml"

  if [ "${_bootstrapping}" = "no" ]; then
    sed -i '/^\[build\]/,/^$/ s|^#||g' "../${_realname}c-${pkgver}-src/config.toml"
  fi
  # generate debuginfo only for non-i686 targets
  if check_option "debug" "y" && [ "${CARCH}" != i686 ]; then
    sed -i 's/^#debug/debug/g' "../${_realname}c-${pkgver}-src/config.toml"
  fi

  # Add target wasm32-*
  if [[ ${CARCH} != i686 ]]; then
    sed -i '/target = \[/a\  "wasm32-unknown-unknown", "wasm32-wasip1", "wasm32-wasip1-threads", "wasm32-wasip2",' "../${_realname}c-${pkgver}-src/config.toml"
  fi

  # Building out of tree is not officially supported so we have to workaround some things like vendored deps
  cp -r ../${_realname}c-${pkgver}-src/.cargo .
  sed -i "s|directory = \"vendor\"|directory = \"../${_realname}c-${pkgver}-src/vendor\"|" .cargo/config.toml

  local -a _rust_build=()
  _rust_build+=("--stage" "2")
  #_rust_build+=("--verbose")

  # create the install at a temporary directory
  DESTDIR="$PWD"/dest-rust python ../${_realname}c-${pkgver}-src/x.py install "${_rust_build[@]}"

  if [[ ${CARCH} != i686 ]]; then
    # move wasm32-* targets out of the way for splitting
    mkdir -p dest-wasm${MINGW_PREFIX}/lib/rustlib
    mv dest-rust${MINGW_PREFIX}/lib/rustlib/wasm32-* dest-wasm${MINGW_PREFIX}/lib/rustlib
  fi

  # move src out of the way for splitting
  mv dest-rust${MINGW_PREFIX}/lib/rustlib/src dest-src

  rm -f dest-rust${MINGW_PREFIX}/lib/rustlib/$OSTYPE/lib/self-contained/*
}

check() {
  cd "${MSYSTEM}"
  python ../${_realname}c-${pkgver}-src/x.py test --stage 2 --exclude src/test/debuginfo
}

package_rust() {
  depends=("${MINGW_PACKAGE_PREFIX}-cc"
           "${MINGW_PACKAGE_PREFIX}-libxml2"
           "${MINGW_PACKAGE_PREFIX}-zstd"
           "${MINGW_PACKAGE_PREFIX}-zlib")
  if [[ ${CARCH} != i686 ]]; then
    optdepends=("${MINGW_PACKAGE_PREFIX}-gdb: for rust-gdb script"
                "${MINGW_PACKAGE_PREFIX}-lldb: for rust-lldb script")
  fi
  conflicts=("${MINGW_PACKAGE_PREFIX}-rust-docs")
  replaces=("${MINGW_PACKAGE_PREFIX}-rust-docs")

  cd "${MSYSTEM}"

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

  # delete unnecessary files, e.g. components and manifest files only used for the uninstall script
  # and rust-{gdb{,gui},lldb} for i686
  cd "${pkgdir}${MINGW_PREFIX}/lib/rustlib"
  rm components install.log manifest-* rust-installer-version uninstall.sh
  if [[ ${CARCH} == i686 ]]; then
    rm "${pkgdir}${MINGW_PREFIX}"/bin/rust-{gdb{,gui},lldb}
  fi

  install -d "${pkgdir}${MINGW_PREFIX}/share/bash-completion/completions"
  mv "${pkgdir}${MINGW_PREFIX}/etc/bash_completion.d/cargo" \
     "${pkgdir}${MINGW_PREFIX}/share/bash-completion/completions/cargo"
}

package_rust-wasm() {
  pkgdesc="WebAssembly targets for Rust (mingw-w64)"
  depends=("${MINGW_PACKAGE_PREFIX}-lld"
           "${MINGW_PACKAGE_PREFIX}-rust"
           "${MINGW_PACKAGE_PREFIX}-wasm-component-ld")
  # object files provided for wasm32-* targets can't be stripped with MSYS2 toolchain
  options=('!strip')

  cd "${MSYSTEM}"

  cp -a dest-wasm/* "${pkgdir}"
  install -Dm644 ../${_realname}c-${pkgver}-src/LICENSE-{APACHE,MIT} -t \
    "${pkgdir}${MINGW_PREFIX}/share/licenses/${_realname}-wasm/"
}

package_rust-src() {
  pkgdesc='Source code for the Rust standard library (mingw-w64)'
  depends=("${MINGW_PACKAGE_PREFIX}-rust")

  cd "${MSYSTEM}"

  install -Dm644 ../${_realname}c-${pkgver}-src/LICENSE-{APACHE,MIT} -t \
    "${pkgdir}${MINGW_PREFIX}/share/licenses/${_realname}-src/"

  install -d "${pkgdir}${MINGW_PREFIX}/lib/rustlib/"
  cp -a dest-src "${pkgdir}${MINGW_PREFIX}/lib/rustlib/src"
}

# template start; name=mingw-w64-splitpkg-wrappers; version=1.0;
# vim: set ft=bash :

# generate wrappers
for _name in "${pkgname[@]}"; do
  _short="package_${_name#${MINGW_PACKAGE_PREFIX}-}"
  _func="$(declare -f "${_short}")"
  eval "${_func/#${_short}/package_${_name}}"
done
# template end;
