# Maintainer: Mateusz Mikuła <oss@mateuszmikula.dev>

_compiler=clang

pkgbase=llvm
pkgname=("llvm"
         "llvm-libs"
         "clang"
         "clang-analyzer"
         "compiler-rt"
         "lld")
_version=21.1.1
_rc=""
_tag=llvmorg-${_version}${_rc}
pkgver=${_version}${_rc/-/}
pkgrel=2
pkgdesc="C language family frontend for LLVM"
arch=('i686' 'x86_64')
url="https://llvm.org/"
msys2_references=(
  "cpe: cpe:/a:llvm:llvm"
)
license=("spdx:Apache-2.0 WITH LLVM-exception")
makedepends=('cmake'
             "$_compiler"
             'ninja'
             'pkgconf'
             'python'
             'git'
             'libzstd-devel'
             'zlib-devel'
             )
_url=https://github.com/llvm/llvm-project/releases/download/${_tag}
source=("${_url}/llvm-${pkgver}.src.tar.xz"{,.sig}
        "${_url}/clang-${pkgver}.src.tar.xz"{,.sig}
        "${_url}/compiler-rt-${pkgver}.src.tar.xz"{,.sig}
        "${_url}/lld-${pkgver}.src.tar.xz"{,.sig}
        "${_url}/cmake-${pkgver}.src.tar.xz"{,.sig}
        "${_url}/libunwind-${pkgver}.src.tar.xz"{,.sig}
        "${_url}/runtimes-${pkgver}.src.tar.xz"{,.sig}
        "${_url}/third-party-${pkgver}.src.tar.xz"{,.sig}
        "0001-hack-tablegentest.patch"
        "0002-LLVM-Cygwin-Enable-conditions-that-are-shared-with-M.patch"
        "0003-lli-Fix-crash-with-no-process-syms-on-MinGW-151386.patch"
        "0004-llvm-Enable-building-Analysis-plugins-on-Cygwin-1513.patch"
        "0005-LLVM-adjust-lit.cfg.py-for-Cygwin-151416.patch"
        "0006-LLVM-Support-Fix-tests-on-Cygwin-151417.patch"
        "0007-LLVM-lit-add-system-cygwin-feature-152780.patch"
        "0008-LLVM-Coverage-Unittest-Fix-dangling-reference-in-uni.patch"
        "0101-Clang-Cygwin-Enable-few-conditions-that-are-shared-w.patch"
        "0102-hack-cygwin-allow-multiple-definition-in-c-index-tes.patch"
        "0103-Cygwin-Internal-class-in-explicitly-instantiation-de.patch"
        "0104-Clang-Cygwin-call-linker-directly.patch"
        "0105-Tests-Add-system-cygwin-feature-and-use-it.-152611.patch"
        "0106-Clang-Cygwin-Use-correct-mangling-rule-158404.patch"
        "0107-Clang-Cygwin-Cygwin-x86_64-should-accept-__stdcall-1.patch"
        "0199-msysize.patch"
        "0201-LLD-COFF-Prevent-to-emit-relocations-for-discarded-w.patch"
        )
sha256sums=('23336f9f2290f2317121a5995e298a4616041ba06cbb07cfd1220a21b48775fe'
            'SKIP'
            '65a19a75440c6d0f92138d82432e7a201677fad5cecf39d3200eaa2f458c29e3'
            'SKIP'
            'f5e46d1734be28bc8ea83d0a5621a43388d349def91e37e6907609e5b67d1f8e'
            'SKIP'
            '5e83536d8197ba38f40b8c4fbdeef7315a7dc15ed894a7b837a9a3482b9f80ef'
            'SKIP'
            '9c0b9064b7d0f2a3004f1d034aadf84d2af4e5dca2135ebf697b0a1eb85ef769'
            'SKIP'
            '1a8847f4c256d2eac5852b8f821205862f925eadf013cd3a660bd8a28a2849ec'
            'SKIP'
            'e28a57f3895f0d652aaaf9389b3db691d4200241815333d9e5edd25c2cdc4c2e'
            'SKIP'
            'e9b7299b0b32aa827231ed35101a3b5ea37dd5a45719225cb2c08ac571791233'
            'SKIP'
            '7cb70e14a5c6e87ef28427356ad3d366d58c367b2039d2a3bf92fa7dee33d79d'
            '275eb63a8d99bf9c3f6168665641fea1010448a9296b3d6b41d1ba1e78d1201e'
            'dec5e5a939486550a260c939e5f0d6d31aa3325f4849524eb79578893f25872b'
            'a4b7a1c928416f649e5e33a49e998ddbd89866e7f3cbb453a389ee210f0d43fa'
            'f6152e93c0e6787609c32d84f097475dab91897102c91f58b8e921b8ceabf25f'
            'dcf2d91ed1ec5e9b885c8de47fe7dc10465491a2b2e686c16a5819da14efbb9c'
            '18066ca1e97147650e139399db91066453b8a3f00ea0c7187b73f5eedbb56927'
            '5580ef79c1cbe3efd0cc4fca078f29879be8764c62b1792fc7f74350ff862a67'
            'c978145529c8f8f0f13192f7d705c7e5359c2c67cc01e0012679847cbbce9e12'
            'b217f87de73cb6255997ef76630e3bc6e9a99398bd713e79d6c6da500620f60b'
            '9b6b248f63e04f810b4d1d919f0b2eb584b08888f0dad11d41e56769e0a01d10'
            '08045ec514a0e9338cc46ad17ffcebb3c421c5eb3dd0ad2bade1bfb4e768f9c2'
            '18320250d0e175d6dabdfa44e6dc6fee6c6ca30ca91e9e1ed1f7c27417b7a671'
            '024e13f86a5d3f181a3068ae7bbb7ba2ab11e062a12b8b949c7803ab1e057a6f'
            'be30d166830d23cb891d380e4e97287d5d88409eda8d0202e90d52fc183f020b'
            '31fb13550d55f7517150fa6a367b8e618f4b5ce21067d4d91d8a5b3d22bd0ad7'
            'fc4b425f9e88200a0baef63d0dbc23c70dce66f3e08fafa85717078c80ae8e2f')
validpgpkeys=('B6C8F98282B944E3B0D5C2530FC3042E345AD05D'  # Hans Wennborg, Google.
              '474E22316ABF4785A88C6E8EA2C794A986419D8A'  # Tom Stellard
              'D574BD5D1D0E98895E3BF90044F2485E45D59042') # Tobias Hieta
noextract=(llvm-${pkgver}.src.tar.xz
           clang-${pkgver}.src.tar.xz)

apply_patch_with_msg() {
  for _patch in "$@"
  do
    msg2 "Applying ${_patch}"
    patch -Nbp1 -i "${srcdir}/${_patch}"
  done
}

revert_patch_with_msg() {
  for _patch in "$@"
  do
    msg2 "Reverting ${_patch}"
    patch -p1 -i "${srcdir}/${_patch}"
  done
}

apply_git_patch_with_msg() {
  for _patch in "$@"
  do
    msg2 "Applying ${_patch}"
    patch -Nbp2 -i "${srcdir}/${_patch}"
  done
}

prepare() {
  cd "${srcdir}"
  plain "Extracting llvm-${pkgver}.src.tar.xz due to symlink(s) without pre-existing target(s)"
  tar -xJf "${srcdir}"/llvm-${pkgver}.src.tar.xz -C "${srcdir}" || true
  plain "Extracting clang-${pkgver}.src.tar.xz due to symlink(s) without pre-existing target(s)"
  tar -xJf "${srcdir}"/clang-${pkgver}.src.tar.xz -C "${srcdir}" || true

  # Rename Directories
  # We need libunwind for LLD: https://github.com/llvm/llvm-project/issues/48572
  for pkg in llvm clang compiler-rt lld cmake libunwind runtimes third-party; do
    mv ${pkg}-$pkgver.src ${pkg}
  done

  # Patch llvm
  cd "${srcdir}"/llvm
  apply_git_patch_with_msg \
    0001-hack-tablegentest.patch \
    0002-LLVM-Cygwin-Enable-conditions-that-are-shared-with-M.patch \
    0003-lli-Fix-crash-with-no-process-syms-on-MinGW-151386.patch \
    0004-llvm-Enable-building-Analysis-plugins-on-Cygwin-1513.patch \
    0005-LLVM-adjust-lit.cfg.py-for-Cygwin-151416.patch \
    0006-LLVM-Support-Fix-tests-on-Cygwin-151417.patch \
    0007-LLVM-lit-add-system-cygwin-feature-152780.patch \
    0008-LLVM-Coverage-Unittest-Fix-dangling-reference-in-uni.patch

  # Patch clang
  cd "${srcdir}"/clang
  apply_git_patch_with_msg \
    0101-Clang-Cygwin-Enable-few-conditions-that-are-shared-w.patch \
    0102-hack-cygwin-allow-multiple-definition-in-c-index-tes.patch \
    0103-Cygwin-Internal-class-in-explicitly-instantiation-de.patch \
    0104-Clang-Cygwin-call-linker-directly.patch \
    0105-Tests-Add-system-cygwin-feature-and-use-it.-152611.patch \
    0106-Clang-Cygwin-Use-correct-mangling-rule-158404.patch \
    0107-Clang-Cygwin-Cygwin-x86_64-should-accept-__stdcall-1.patch

  apply_git_patch_with_msg \
    0199-msysize.patch

  # Patch lld
  cd "${srcdir}"/lld
  apply_git_patch_with_msg \
    0201-LLD-COFF-Prevent-to-emit-relocations-for-discarded-w.patch
}

build() {
  local -a platform_config
  local -a common_cmake_args

  if check_option "debug" "y"; then
    common_cmake_args+=(-DCMAKE_BUILD_TYPE=Debug
                        -DLLVM_ENABLE_ASSERTIONS=ON)
    VERBOSE="VERBOSE=1"
  else
    common_cmake_args+=(-DCMAKE_BUILD_TYPE=Release
                        -DLLVM_ENABLE_ASSERTIONS=OFF
                        -DLLVM_ENABLE_DUMP=ON)
  fi
  common_cmake_args+=(-Wno-dev
    -DCMAKE_INSTALL_PREFIX=/usr
    -DCOMPILER_RT_BUILD_ORC=OFF
    -DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON
    -DCOMPILER_RT_INCLUDE_TESTS=OFF
    -DCOMPILER_RT_OS_DIR=cygwin
    -DLLVM_DEFAULT_TARGET_TRIPLE=${CARCH}-pc-windows-cygnus
    -DLLVM_ENABLE_THREADS=ON
    -DLLVM_HOST_TRIPLE=${CARCH}-pc-windows-cygnus
    -DLLVM_INCLUDE_BENCHMARKS=OFF
    -DLLVM_INCLUDE_TESTS=ON
    -DLLVM_USE_SYMLINKS=OFF
    -DPython3_EXECUTABLE=/usr/bin/python.exe
  )

  if [ "${_compiler}" == "gcc" ]; then
    common_cmake_args+=(
      -DLIBCLANG_BUILD_STATIC=ON
      -DLLVM_ENABLE_PIC=OFF
    )
  elif [ "${_compiler}" == "clang" ]; then
    export CC='clang'
    export CXX='clang++'
    common_cmake_args+=(
      -DLLVM_BUILD_LLVM_DYLIB=ON
      -DLLVM_LINK_LLVM_DYLIB=ON
    )
  else
    error "Unsupported compiler: $_compiler"
    exit 1
  fi

  local _projects="clang;lld"

  platform_config+=(-DLLVM_TARGETS_TO_BUILD="AArch64;ARM;X86")

  cmake \
    -GNinja \
    -B build \
    -DLLVM_ENABLE_PROJECTS="${_projects}" \
    -DLLVM_ENABLE_RUNTIMES="compiler-rt" \
    -DLLVM_ENABLE_RTTI=ON \
    -DLLD_DEFAULT_LD_LLD_IS_MINGW=ON \
    "${common_cmake_args[@]}" \
    "${platform_config[@]}" \
    llvm

  cmake --build build
}

check() {
  cd "${srcdir}/build"
  MSYS=winsymlinks:sys ln -sf msys-clang-${pkgver%.*}.dll bin/libclang.so
  MSYS=winsymlinks:sys PATH="${srcdir}/build/bin:$PATH" ninja -k0 check-all || true
}

package_clang() {
  pkgdesc="C language family frontend for LLVM"
  url="https://clang.llvm.org/"
  depends=("gcc" "llvm-libs=${pkgver}")
  optdepends=("compiler-rt: for -rtlib=compiler-rt"
              "llvm=${pkgver}")

  # Disable automatic installation of components that go into subpackages
  # -i.orig to check what has been removed in-case it starts dropping more than it should
  sed -i.orig '/\(extra\|scan-build\|scan-build-py\|scan-view\)\/cmake_install.cmake/d' "${srcdir}"/build/tools/clang/tools/cmake_install.cmake
  DESTDIR="${pkgdir}" cmake --install "${srcdir}"/build/tools/clang

  install -Dm644 "${srcdir}"/clang/LICENSE.TXT "${pkgdir}"/usr/share/licenses/clang/LICENSE

  # Install Python bindings
  site_packages=$(python -c "import site; print(site.getsitepackages()[0])")
  install -d "${pkgdir}"/${site_packages}
  cp -a "${srcdir}"/clang/bindings/python/clang "${pkgdir}"/${site_packages}
  python -m compileall -o 0 -o 1 "${pkgdir}"/${site_packages}
}

package_clang-analyzer() {
  pkgdesc="A source code analysis framework"
  url="https://clang-analyzer.llvm.org/"
  depends=("clang=${pkgver}" "python")

  local _analyzer
  for _analyzer in scan-build scan-build-py scan-view; do
    DESTDIR="${pkgdir}" cmake --install "${srcdir}"/build/tools/clang/tools/${_analyzer}
  done

  # Compile Python scripts
  python -m compileall -o 0 -o 1 "${pkgdir}"/usr/lib/libscanbuild

  install -Dm644 "${srcdir}"/clang/LICENSE.TXT "${pkgdir}"/usr/share/licenses/clang-analyzer/LICENSE
}

package_compiler-rt() {
  pkgdesc="Runtime libraries for Clang and LLVM"
  url="https://compiler-rt.llvm.org/"
  depends=("gcc-libs")

  DESTDIR="${pkgdir}" cmake --install "${srcdir}"/build/runtimes/builtins-bins
  DESTDIR="${pkgdir}" cmake --install "${srcdir}"/build/runtimes/runtimes-bins

  install -Dm644 "${srcdir}"/compiler-rt/LICENSE.TXT "${pkgdir}"/usr/share/licenses/compiler-rt/LICENSE
}

package_lld() {
  pkgdesc="Linker tools for LLVM"
  url="https://lld.llvm.org/"
  depends=("gcc-libs" "llvm-libs=${pkgver}")

  DESTDIR="${pkgdir}" cmake --install "${srcdir}"/build/tools/lld

  install -Dm644 "${srcdir}"/lld/LICENSE.TXT "${pkgdir}"/usr/share/licenses/lld/LICENSE
}

package_llvm() {
  pkgdesc="Low Level Virtual Machine"
  depends=("llvm-libs=${pkgver}")

  # Disable automatic installation of components that go into subpackages
  # -i.orig to check what has been removed in-case it starts dropping more than it should
  sed -i.orig '/\(clang\|lld\)\/cmake_install.cmake/d' "${srcdir}"/build/tools/cmake_install.cmake
  sed -i.orig '/\(builtins\|runtimes\)-bins\/\+cmake_install.cmake/d' "${srcdir}"/build/runtimes/cmake_install.cmake
  DESTDIR="${pkgdir}" cmake --install "${srcdir}"/build

  # Runtime libraries
  rm -rf "${srcdir}"/llvm-libs
  mkdir -p "${srcdir}"/llvm-libs/usr/bin
  mv -f "${pkgdir}"/usr/bin/msys-*.dll "${srcdir}"/llvm-libs/usr/bin

  install -Dm644 "${srcdir}"/llvm/LICENSE.TXT "${pkgdir}"/usr/share/licenses/llvm/LICENSE

  # Install CMake stuff
  install -d "${pkgdir}"/usr/share/llvm/cmake/{modules,platforms}
  install -Dm644 "${srcdir}"/llvm/cmake/modules/*.cmake "${pkgdir}"/usr/share/llvm/cmake/modules/
  install -Dm644 "${srcdir}"/llvm/cmake/platforms/*.cmake "${pkgdir}"/usr/share/llvm/cmake/platforms/

  # fix cmake files.
  sed -e "s|${srcdir}/build|/usr|g" -i ${pkgdir}/usr/lib/cmake/llvm/LLVMConfig.cmake
}

package_llvm-libs() {
  pkgdesc="Low Level Virtual Machine Runtime Libraries"
  depends=("gcc-libs" "libzstd" "zlib")
  conflicts=("llvm<21.1.0")

  cp -r "${srcdir}"/llvm-libs/usr "${pkgdir}"/usr
  # HACK to keep rust working to rebuild itself
  #cp /usr/bin/msys-LLVM-20.dll "${pkgdir}"/usr/bin

  install -Dm644 "${srcdir}"/llvm/LICENSE.TXT "${pkgdir}"/usr/share/licenses/llvm-libs/LICENSE
}
