# Maintainer: Martell Malone <martellmalone@gmail.com>
# Maintainer: Alexey Pavlov <alexpux@gmail.com>
# Contributor: Ray Donnelly <mingw.android@gmail.com>
# Contributor: Mateusz Mikuła <mati865@gmail.com>
# Contributor: wirx6 <wirx654@gmail.com>
# Contributor: Yuui Tanabe <yuuitanabe@163.com>
# Contributor: Oscar Fuentes <ofv@wanadoo.es>
# Contributor: Adrian Pop <adrian.pop@liu.se>

_realname=llvm
pkgbase=mingw-w64-${_realname}-21
pkgname=("${MINGW_PACKAGE_PREFIX}-llvm-21"
         "${MINGW_PACKAGE_PREFIX}-clang-21"
         "${MINGW_PACKAGE_PREFIX}-compiler-rt-21"
         "${MINGW_PACKAGE_PREFIX}-lld-21")
_pkgver=21.1.8
pkgver=${_pkgver/-/}
pkgrel=3
pkgdesc="C language family frontend for LLVM (mingw-w64)"
arch=('any')
mingw_arch=('mingw64' 'ucrt64' 'clang64' 'clangarm64')
url="https://llvm.org/"
msys2_repository_url="https://github.com/llvm/llvm-project"
msys2_references=(
  "cpe: cpe:/a:llvm:llvm"
)
license=("spdx:Apache-2.0 WITH LLVM-exception")
groups=($( [[ ${MINGW_PACKAGE_PREFIX} == *-clang-* ]] && echo "${MINGW_PACKAGE_PREFIX}-toolchain"))
makedepends=("${MINGW_PACKAGE_PREFIX}-cc"
             "${MINGW_PACKAGE_PREFIX}-cmake"
             "${MINGW_PACKAGE_PREFIX}-ninja"
             "${MINGW_PACKAGE_PREFIX}-pkgconf"
             "${MINGW_PACKAGE_PREFIX}-libffi"
             "${MINGW_PACKAGE_PREFIX}-libunwind"
             "${MINGW_PACKAGE_PREFIX}-z3"
             "${MINGW_PACKAGE_PREFIX}-zstd"
             "${MINGW_PACKAGE_PREFIX}-python"
             "git"
             )
_url=https://github.com/llvm/llvm-project/releases/download/llvmorg-${_pkgver}
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}/third-party-${_pkgver}.src.tar.xz"{,.sig}
        # 0001-0099 -> llvm
        "0001-Fix-GetHostTriple-for-mingw-w64-in-msys.patch"
        "0002-Fix-Findzstd-on-MINGW.patch"
        "0003-add-pthread-as-system-lib-for-mingw.patch"
        "0004-enable-emutls-for-mingw.patch"
        # 0101-0199 -> clang
        "0101-link-pthread-with-mingw.patch"
        # 0201-0299 -> rt
        # 0301-0399 -> lld
        "0303-ignore-new-bfd-options.patch"
        "4001-build-fix-backport.patch"
        )
sha256sums=('d9022ddadb40a15015f6b27e6549a7144704ded8828ba036ffe4b8165707de21'
            'SKIP'
            '6090e3f23720d003cdd84483a47d0eec6d01adbb5e0c714ac0c8b58de546aa62'
            'SKIP'
            'dd54ae21aee1780fac59445b51ebff601ad016b31ac3a7de3b21126fd3ccb229'
            'SKIP'
            'd9524c5ee952500a2af92c27042a0d90ab089962af47816d4c85d0ebf76373d1'
            'SKIP'
            '85735f20fd8c81ecb0a09abb0c267018475420e93b65050cc5b7634eab744de9'
            'SKIP'
            '7fe99424384aea529ffaeec9cc9dfb8b451fd1852c03fc109e426fe208a1f1a7'
            'SKIP'
            'eb03df53671df6627768141b3aaa76abe176a14e5e47911c97bec544387c4aff'
            'd77d47e37e4948f5c01ae8bc05fb4e879b6516132c5a60c7bc820c9cbbb39668'
            '790eb0fccb4ef29c3795bceb8a62c8f4ecd0bdd6c49b2812352b04cfbc552342'
            '76d2a88733cebb1f01b766ff2ab91a9e095bae1d2e4cc18c1ffcf21fd095efc4'
            '715cb8862753854b2d9256e0b70003e2d1f57083d83eaeaf5a095fc72b8a4e26'
            'fd0253879cc5e31857f57307e6105e56493358e35d7c4540e0b476be607ab94e'
            'eff54a4fc69dd0ca6e4f75cd63b1d1335c5e8b2e4de3b1c7a1f54239c0aa0519')
validpgpkeys=('B6C8F98282B944E3B0D5C2530FC3042E345AD05D'  # Hans Wennborg, Google.
              '474E22316ABF4785A88C6E8EA2C794A986419D8A'  # Tom Stellard
              '71046D1E9C6656BDD61171873E83BABF4A4F9E85'  # Cullen Rhodes
              'FFB3368980F3E6BB5737145A316C56D064CACBA5'  # Douglas Yung
              'D574BD5D1D0E98895E3BF90044F2485E45D59042') # Tobias Hieta
noextract=(clang-${_pkgver}.src.tar.xz
           llvm-${_pkgver}.src.tar.xz)

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

prepare() {
  cd "${srcdir}"
  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

  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

  # Rename Directories
  for pkg in llvm clang compiler-rt lld cmake third-party; do
    mv ${pkg}-${_pkgver}.src ${pkg}
  done

  # Patch llvm
  cd "${srcdir}"/llvm
  apply_patch_with_msg \
    "0001-Fix-GetHostTriple-for-mingw-w64-in-msys.patch" \
    "0002-Fix-Findzstd-on-MINGW.patch"

  if [[ ${MINGW_PACKAGE_PREFIX} != *-clang-* ]]; then
    apply_patch_with_msg \
      "0003-add-pthread-as-system-lib-for-mingw.patch" \
      "0004-enable-emutls-for-mingw.patch"
  fi

  # Patch clang
  cd "${srcdir}"/clang

  if [[ ${MINGW_PACKAGE_PREFIX} != *-clang-* ]]; then
    apply_patch_with_msg \
      "0101-link-pthread-with-mingw.patch"
  fi

  # Patch lld
  cd "${srcdir}"/lld

  apply_patch_with_msg \
    "0303-ignore-new-bfd-options.patch"

  # Patch whole tree
  cd "${srcdir}"

  # https://github.com/llvm/llvm-project/issues/183908#issuecomment-4060452054
  apply_patch_with_msg \
    4001-build-fix-backport.patch
}

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

  # Include location of libffi headers in CPPFLAGS
  FFI_INCLUDE_DIR="$(pkg-config --cflags libffi)"
  FFI_INCLUDE_DIR=$(echo $FFI_INCLUDE_DIR | sed 's|-I||g')

  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=${MINGW_PREFIX}/opt/llvm-21
    -DCMAKE_SYSTEM_IGNORE_PATH=/usr/lib
    -DLLVM_HOST_TRIPLE="${CARCH}-w64-windows-gnu"
    -DLLVM_BUILD_STATIC=ON
    -DLLVM_BUILD_LLVM_DYLIB=OFF
    -DLLVM_LINK_LLVM_DYLIB=OFF
    -DLLVM_ENABLE_FFI=ON
    -DLLVM_ENABLE_THREADS=ON
    -DLLVM_INCLUDE_EXAMPLES=OFF
    -DLLVM_INCLUDE_BENCHMARKS=OFF
    -DLLVM_INCLUDE_TESTS=OFF
    -DPython3_EXECUTABLE=${MINGW_PREFIX}/bin/python.exe
    -DFFI_INCLUDE_DIR="${FFI_INCLUDE_DIR}")

  if [[ ${MINGW_PACKAGE_PREFIX} == *-clang-* ]]; then
    # A bit hacky but it works
    local _clang_links="clang++;clang-cpp;as;c++;cc;cpp;${MINGW_CHOST}-cc;${MINGW_CHOST}-c++;${MINGW_CHOST}-clang;${MINGW_CHOST}-clang++"

    platform_config+=(
      -DLLVM_ENABLE_LIBCXX=ON
      -DLLVM_ENABLE_LLD=ON
      -DLLVM_INSTALL_BINUTILS_SYMLINKS=ON
      -DCLANG_DEFAULT_LINKER=lld
      -DCLANG_DEFAULT_RTLIB=compiler-rt
      -DCLANG_DEFAULT_UNWINDLIB=libunwind
      -DCLANG_DEFAULT_CXX_STDLIB=libc++
      -DCLANG_LINKS_TO_CREATE="${_clang_links}"
      -DCOMPILER_RT_USE_BUILTINS_LIBRARY=ON
      -DCOMPILER_RT_EXCLUDE_ATOMIC_BUILTIN=OFF
    )
  fi

  local _projects="clang;compiler-rt;lld"

  case "${CARCH}" in
    x86_64|i?86)
      platform_config+=(-DCOMPILER_RT_BUILD_SANITIZERS=$( [[ ${MINGW_PACKAGE_PREFIX} == *-clang-* ]] && echo "ON" || echo "OFF"))
      ;;
    armv7|aarch64)
      platform_config+=(
        -DCOMPILER_RT_BUILD_MEMPROF=OFF
        -DCOMPILER_RT_BUILD_SANITIZERS=OFF
        -DCOMPILER_RT_BUILD_XRAY=OFF
      )
      ;;
  esac

  # List of targets to build in CMake style
  # For more info see: https://github.com/msys2/MINGW-packages/discussions/9765
  if [[ ${MINGW_PACKAGE_PREFIX} == *-clang-* ]]; then
    platform_config+=(-DLLVM_TARGETS_TO_BUILD="all")
  else
    platform_config+=(-DLLVM_TARGETS_TO_BUILD="AArch64;ARM;RISCV;X86")
  fi

  MSYS2_ARG_CONV_EXCL="-DCMAKE_INSTALL_PREFIX=" \
  ${MINGW_PREFIX}/bin/cmake.exe \
    -GNinja \
    -DLLVM_ENABLE_PROJECTS="${_projects}" \
    -DLLVM_ENABLE_RTTI=ON \
    -DLLVM_INSTALL_UTILS=ON \
    -DLLVM_USE_STATIC_ZSTD=ON \
    -DLIBCLANG_BUILD_STATIC=ON \
    -DCOMPILER_RT_ENABLE_WERROR=OFF \
    -DCOMPILER_RT_HAS_WBUILTIN_DECLARATION_MISMATCH_FLAG=OFF \
    -DLLD_DEFAULT_LD_LLD_IS_MINGW=ON \
    "${common_cmake_args[@]}" \
    "${platform_config[@]}" \
    -S llvm \
    -B build-${MSYSTEM}

  ${MINGW_PREFIX}/bin/cmake.exe --build build-${MSYSTEM}
}

package_clang-21() {
  pkgdesc="C language family frontend for LLVM 21.1 (mingw-w64)"
  url="https://clang.llvm.org/"
  depends=("${MINGW_PACKAGE_PREFIX}-compiler-rt-21" \
           "${MINGW_PACKAGE_PREFIX}-llvm-21"
           $( [[ ${MINGW_PACKAGE_PREFIX} == *-clang-* ]] && echo \
             "${MINGW_PACKAGE_PREFIX}-crt" \
             "${MINGW_PACKAGE_PREFIX}-headers" \
             "${MINGW_PACKAGE_PREFIX}-lld" \
             "${MINGW_PACKAGE_PREFIX}-winpthreads" || echo \
             "${MINGW_PACKAGE_PREFIX}-gcc"))

  DESTDIR="${pkgdir}" ${MINGW_PREFIX}/bin/cmake --install "${srcdir}"/build-${MSYSTEM}/tools/clang

  install -Dm644 "${srcdir}"/clang/LICENSE.TXT \
    "${pkgdir}"${MINGW_PREFIX}/opt/llvm-21/share/licenses/clang/LICENSE
}

package_compiler-rt-21() {
  pkgdesc="Runtime libraries for Clang and LLVM 21.1 (mingw-w64)"
  url="https://compiler-rt.llvm.org/"
  depends=($([[ ${MINGW_PACKAGE_PREFIX} != *-clang-* ]] || echo "${MINGW_PACKAGE_PREFIX}-cc-libs"))

  DESTDIR="${pkgdir}" ${MINGW_PREFIX}/bin/cmake --install "${srcdir}"/build-${MSYSTEM}/projects/compiler-rt
  mkdir -p "${pkgdir}"${MINGW_PREFIX}/opt/llvm-21/bin/
  find "${pkgdir}"${MINGW_PREFIX}/opt/llvm-21/lib/clang/${pkgver%.[0-9].*}/lib/windows/ \
    -name '*.dll' -exec mv '{}' "${pkgdir}"${MINGW_PREFIX}/opt/llvm-21/bin/ \;
  # remove bin dir we created if it is still empty
  rmdir "${pkgdir}"${MINGW_PREFIX}/opt/llvm-21/bin/ 2>/dev/null || true

  install -Dm644 "${srcdir}"/compiler-rt/LICENSE.TXT \
    "${pkgdir}"${MINGW_PREFIX}/opt/llvm-21/share/licenses/compiler-rt/LICENSE
}

package_lld-21() {
  pkgdesc="Linker tools for LLVM 21.1 (mingw-w64)"
  url="https://lld.llvm.org/"

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

  install -Dm644 "${srcdir}"/lld/LICENSE.TXT \
    "${pkgdir}"${MINGW_PREFIX}/opt/llvm-21/share/licenses/lld/LICENSE
}

package_llvm-21() {
  pkgdesc="Low Level Virtual Machine 21.1 (mingw-w64)"
  depends=("${MINGW_PACKAGE_PREFIX}-cc-libs")

  # 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' build-${MSYSTEM}/tools/cmake_install.cmake
  sed -i.orig '/compiler-rt\/cmake_install.cmake/d' build-${MSYSTEM}/projects/cmake_install.cmake
  DESTDIR="${pkgdir}" ${MINGW_PREFIX}/bin/cmake --install build-${MSYSTEM}

  install -Dm644 "${srcdir}"/llvm/LICENSE.TXT \
    "${pkgdir}"${MINGW_PREFIX}/opt/llvm-21/share/licenses/llvm/LICENSE

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

  # fix cmake files.
  local PREFIX_WIN=$(cygpath -wm ${MINGW_PREFIX})
  sed -e "s|${PREFIX_WIN}|${MINGW_PREFIX}|g" -i "${pkgdir}"/${MINGW_PREFIX}/opt/llvm-21/lib/cmake/llvm/LLVMExports.cmake
}

# 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;
