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

_compiler=clang

pkgbase=llvm
pkgname=("llvm"
         "clang"
         "clang-analyzer"
         "compiler-rt"
         "lld")
_version=20.1.6
_rc=""
_tag=llvmorg-${_version}${_rc}
pkgver=${_version}${_rc/-/}
pkgrel=1
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-LLVM-Cygwin-Fix-symbol-visibility-definition.patch"
        "0002-LLVM-Cygwin-Remove-special-case-for-CXX-extensions-o.patch"
        "0003-LLVM-Cygwin-Fix-shared-library-name-136599.patch"
        "0004-LLVM-Cygwin-Fix-Signals-compatibility-with-Cygwin-AP.patch"
        "0005-LLVM-TargetParser-Handle-msys-targets-the-same-as-cy.patch"
        "0006-LLVM-Cygwin-Define-_GNU_SOURCE-on-Cygwin-as-well.-13.patch"
        "0007-Cygwin-Emit-COMDAT-name-correctly-for-Cygwin-138621.patch"
        "0008-LLVM-Cygwin-add-workaround-for-blocking-connect-acce.patch"
        "0009-Support-Cygwin-Fix-handling-of-Process-symbol-lookup.patch"
        "0101-Cygwin-Global-symbols-should-be-external-by-default-.patch"
        "0102-Clang-Cygwin-Enable-few-conditions-that-are-shared-w.patch"
        "0103-Cygwin-Enable-TLS-on-Cygwin-target-138618.patch"
        "0104-Clang-Cygwin-Fix-symbol-visibility-definition-138118.patch"
        "0105-Cygwin-RTTI-and-VTable-should-be-dllexport-ed-139798.patch"
        "0106-Clang-Cygwin-Disable-shared-libs-on-Cygwin-by-defaul.patch"
        "0107-Clang-Cygwin-Remove-erroneous-_WIN32-define-and-clea.patch"
        "0108-Clang-Cygwin-don-t-use-Bsymbolic-functions-138217.patch"
        "0109-hack-cygwin-allow-multiple-definition-c-index-test.patch"
        "0110-Clang-Driver-add-a-Cygwin-ToolChain-135691.patch"
        "0111-Clang-Driver-use-__cxa_atexit-by-default-on-Cygwin.-.patch"
        "0112-Clang-CMake-use-CMakePushCheckState-138783.patch"
        "0113-CMake-respect-LLVMConfig.cmake-s-LLVM_DEFINITIONS.patch"
        "0114-Cygwin-Internal-class-in-explicitly-instantiation-de.patch"
        "0115-Cygwin-Template-instantiations-should-be-exported-by.patch"
        "0116-Cygwin-va_list-must-be-treated-like-normal-Windows.patch"
        "0117-Cygwin-wint_t-is-unsigned-int.patch"
        "0201-LLD-MinGW-Implement-dll-search-prefix-option.patch"
        "0203-LLD-COFF-add-__-data-bss-_-start-end-__-symbols-for-.patch"
        "0204-LLD-MinGW-Fall-back-to-using-default-target-if-no-m-.patch"
        "0205-LLD-COFF-Ensure-.bss-is-merged-at-the-end-of-a-secti.patch"
        "0206-LLD-CMake-fix-testing-standalone-build-without-insta.patch"
        )
sha256sums=('f09e304ca98bb809f492ec34f94f587361b4b0d06ed783fb3a41e7fb218e47a1'
            'SKIP'
            '49a16d6b6878a6bdd9ead2d31ffb94c792675607471afa40096fbd48b3cbab66'
            'SKIP'
            '34ff389ce2c34ac1fe8badcf842265295daa91fd1149d69a7ebaf131edf01e4d'
            'SKIP'
            '280239aa9d9b94df484022cd7c28e5601acea5d60d06bc99d6b7de5b4dc516fe'
            'SKIP'
            'b4b3efa5d5b01b3f211f1ba326bb6f0c318331f828202d332c95b7f30fca5f8c'
            'SKIP'
            'bdf90d0428c2cb7b763677c0932509b6dca9f210183e9e73c129ab32d7b658ef'
            'SKIP'
            'fde825adf348b4cb3b778d8d0409a1ecab2ac0d5ae27031a4530756e909db2d8'
            'SKIP'
            '33530189d31b2396b76a7ebac8f938747b3619154cc37015cef9dea29292f7e2'
            'SKIP'
            'c69263b63ffc72c477ef1ecefa07ac8c1aa3e6ffa566df9ce04dc8516e97d8d3'
            '268f6ae784614589c424fb54283e521fad88a92ef5327b7d4cfe3b3963d52d31'
            '83199ac8025b2b1df48c1dbbeba2e5e444d2f6affabf00faf3b4fa7071fd658a'
            '1188bbf3596f9d61681b841dfe48c94e629037e3af538aeb297d472b1981175f'
            '12f5ff853e858a61b356fb7b8e6e16dda181abcf5ceba03a6df758f680b396f1'
            '301d5bf2abaaa333aa7248469f14ab1f2995c822ba6f18de75a922667308def0'
            '019bc12062950db80299b6022b73496dbcd358d55d0bb59ce7f52c45da5a4bdc'
            '6c739a086b070ca17c907199b03084393b31bef8e166c6c05ec0af2a785b6c3c'
            'f44242c25a382f47b0a7e5efc68a300bb169c868fb6a36b2ad0a3590042d4e5a'
            '85d6a8dcde9f8bd40f0f4e47cef584c53d130105a0e475b167a99e6f098082c9'
            '3060198177aafc4994694b5897b736e4690f2bd722e1650272d88c574a5b394d'
            'c78a73153781408238da59e006b5da0a033d42bc6930a6730b79a793d0ac6ef6'
            'f0a47588e84fb84c919bb059349929653d2c938219165fb31b054a474f5fb7eb'
            '653c6b213d5397da74a2be9fbe3401558248422375067e4c32e5cd37b591b2d2'
            'bc6bee32789ea619196617a81d7e8cf7ed413f8416d79263c09db38564a4d1fc'
            '336c8cb9cbb9c5674dd67fa62f695dbf40b629b91b71cc2eecfff5f384e3da61'
            '9e67538a4f42aa1a9c81874d4dd2fa7f9b710bc56fc02bb400f5ffed15e10572'
            'ba77a47634a0e99080ce3097d6d87b02b4904d80f4a809cac0124d31a2a0e829'
            '53f1e7af7855e92053b2ccba263912918dd5980ed03b05c61148f5f9b20f8835'
            '57e270f388e94817ae0ce64fada93d9e1ab1b0918008e8719b80cd032a860e16'
            '61aa7263e3b50c85b87560ca9ef141d71660b4ebb4fc1b11f2330105d5361af0'
            '5945b60d9050f8aa0cab0772ea1a9c7618a58a9ebb3cae7a65df318f2ada870d'
            'fcb909c94af1483424e510c50f84d7aad5631eef5de048617437db5cff3836c1'
            '94a8a2db43b2808a39b440d49ebb0d07dc84137977d35f86e9c616758b9adc13'
            'd79df031d31b47a952300850289a77b8bbf187f802ac64534a0eb1197813c989'
            '6f87c81cee08d6d9a6c4dba75f0cd636f2e30283ca1f6e5b7ae737e741f9d85a'
            '0ddada23a1d060817b06a081d6f3fbb45a86dea9c0632d79f747c9a35a7a26b4'
            '63fbf5fb4845521772fdd3d699188f8cf30a99999ed639a66bdb1d236a14e5d4'
            'c5cbfb64eb7b19d6f1f1c1eb9c3278fcfbed8bfc482f8f36025cbdd3eef642a5'
            'a94a90b514105550e4e1a0502c1400d470d800fb137df4cf45f9a03fea224804'
            '3387f86dc38909d057d5697cde90d6f801a8c8f09b5591de1e751b9172c76931')
validpgpkeys=('B6C8F98282B944E3B0D5C2530FC3042E345AD05D'  # Hans Wennborg, Google.
              '474E22316ABF4785A88C6E8EA2C794A986419D8A'  # Tom Stellard
              'D574BD5D1D0E98895E3BF90044F2485E45D59042') # Tobias Hieta
noextract=(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 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-LLVM-Cygwin-Fix-symbol-visibility-definition.patch
  apply_git_patch_with_msg 0002-LLVM-Cygwin-Remove-special-case-for-CXX-extensions-o.patch
  apply_git_patch_with_msg 0003-LLVM-Cygwin-Fix-shared-library-name-136599.patch
  apply_git_patch_with_msg 0004-LLVM-Cygwin-Fix-Signals-compatibility-with-Cygwin-AP.patch
  apply_git_patch_with_msg 0005-LLVM-TargetParser-Handle-msys-targets-the-same-as-cy.patch
  apply_git_patch_with_msg 0006-LLVM-Cygwin-Define-_GNU_SOURCE-on-Cygwin-as-well.-13.patch
  apply_git_patch_with_msg 0007-Cygwin-Emit-COMDAT-name-correctly-for-Cygwin-138621.patch
  apply_git_patch_with_msg 0008-LLVM-Cygwin-add-workaround-for-blocking-connect-acce.patch
  apply_git_patch_with_msg 0009-Support-Cygwin-Fix-handling-of-Process-symbol-lookup.patch

  # Patch clang
  cd "${srcdir}"/clang
  apply_git_patch_with_msg 0101-Cygwin-Global-symbols-should-be-external-by-default-.patch
  apply_git_patch_with_msg 0102-Clang-Cygwin-Enable-few-conditions-that-are-shared-w.patch
  apply_git_patch_with_msg 0103-Cygwin-Enable-TLS-on-Cygwin-target-138618.patch
  apply_git_patch_with_msg 0104-Clang-Cygwin-Fix-symbol-visibility-definition-138118.patch
  apply_git_patch_with_msg 0105-Cygwin-RTTI-and-VTable-should-be-dllexport-ed-139798.patch
  apply_git_patch_with_msg 0106-Clang-Cygwin-Disable-shared-libs-on-Cygwin-by-defaul.patch
  apply_git_patch_with_msg 0107-Clang-Cygwin-Remove-erroneous-_WIN32-define-and-clea.patch
  apply_git_patch_with_msg 0108-Clang-Cygwin-don-t-use-Bsymbolic-functions-138217.patch
  apply_git_patch_with_msg 0109-hack-cygwin-allow-multiple-definition-c-index-test.patch
  apply_git_patch_with_msg 0110-Clang-Driver-add-a-Cygwin-ToolChain-135691.patch
  apply_git_patch_with_msg 0111-Clang-Driver-use-__cxa_atexit-by-default-on-Cygwin.-.patch
  apply_git_patch_with_msg 0112-Clang-CMake-use-CMakePushCheckState-138783.patch
  apply_git_patch_with_msg 0113-CMake-respect-LLVMConfig.cmake-s-LLVM_DEFINITIONS.patch
  apply_git_patch_with_msg 0114-Cygwin-Internal-class-in-explicitly-instantiation-de.patch
  apply_git_patch_with_msg 0115-Cygwin-Template-instantiations-should-be-exported-by.patch
  apply_git_patch_with_msg 0116-Cygwin-va_list-must-be-treated-like-normal-Windows.patch
  apply_git_patch_with_msg 0117-Cygwin-wint_t-is-unsigned-int.patch

  # Patch lld
  cd "${srcdir}"/lld
  apply_git_patch_with_msg 0201-LLD-MinGW-Implement-dll-search-prefix-option.patch
  apply_git_patch_with_msg 0203-LLD-COFF-add-__-data-bss-_-start-end-__-symbols-for-.patch
  apply_git_patch_with_msg 0204-LLD-MinGW-Fall-back-to-using-default-target-if-no-m-.patch
  apply_git_patch_with_msg 0205-LLD-COFF-Ensure-.bss-is-merged-at-the-end-of-a-secti.patch
  apply_git_patch_with_msg 0206-LLD-CMake-fix-testing-standalone-build-without-insta.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
    -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=OFF
    -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
}

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

  # 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=${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=("gcc-libs" "libzstd" "zlib")

  # 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

  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
}
