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

_compiler=clang

pkgbase=llvm
pkgname=("llvm"
         "clang"
         "clang-analyzer"
         "compiler-rt"
         "lld")
_version=20.1.4
_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"
        "0102-Clang-Cygwin-Enable-few-conditions-that-are-shared-w.patch"
        "0103-Clang-Cygwin-Enable-TLS.patch"
        "0104-Clang-Cygwin-Fix-symbol-visibility-definition-138118.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.patch"
        "0111-Clang-Driver-use-__cxa_atexit-by-default-on-Cygwin.-.patch"
        "0112-hack-cygwin-define-_GLIBCXX_USE_CXX11_ABI-to-1-if-no.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"
        )
sha256sums=('98a95e4a86dd50d0177ae058365e08da0569ad843e829a68489a0d217e5c4411'
            'SKIP'
            'f26454224190c2090e5d21be8700abbc56592a0c0764291a5c358f2974f1fde3'
            'SKIP'
            'dc4d01aa3ccb6484d74d6d978d7f46e2f3b317dee708e0d7194055203008c6c7'
            'SKIP'
            '8aef45513ca779fd83de1bc6dee0ee6c434f3e72f574a4628a5a507b288a635f'
            'SKIP'
            'd6fe52e4fd709590284127cfef143f67ff1b917865f1b4731f6600c330bf9c27'
            'SKIP'
            '6be6213cdb628af13b29c6c45a1eb8f2181fa1590cffce6e7f7ba7508cfccede'
            'SKIP'
            '5a559ab91fe5963c69f9b7838f364e0ab72e1a6cca9b9cbadf8426f93a203a9c'
            'SKIP'
            '94a42d62aaf96b260f01217e170620bd120eaf70926930a58c8c451aceb9c015'
            'SKIP'
            '0f446bd4886fc6eac575c7a7e8dcfc84d1186eb79f73e321966bccc214e57271'
            '32419b37a32c8387dc0df1a54d9459a046eaf8ba6564df6573c54829b50b850a'
            '01adbbd20926ea99c2eba7a8d691dbe12755315fb27e1000d822b6e2691705f9'
            '3b4fdc72da4f23c7656b8a2f0a168904b294abcd7dcc2151e59a7aa63581e37a'
            '19be8aaa4ea24249ca750ab2a84fdf6ab9a03aee012f3f377d9525d7a6d3e7d9'
            '93b81f87a9444d8a1375c8f47cb1caed22359048839ae4eca0db52dd40c24077'
            'ff593fa117c7a05fc1d68622d78b8e9d62fbf1fd647ac955cb3e3fc2138a1b30'
            'ee018e5a11ccd72808ef0a757a50e6119576620c0176e09104ddd3f6ac898f66'
            'ddf4d7ae7aa1ec974a4c6f927572823f51e6e3af0e82a6142c37fe2c83be2eb5'
            '46d4270226003ba4777f45a3f45d1a391bbde4dcecd9bf0c24242d3fa828f1a2'
            '325069aa129cd7507e52541c3bd23577e99b0208a9d14053ee7d49da37bdcc51'
            'a47b97820b0bd158d9e00f4abd0195cc5379f1861e359485dafc433604d0a64a'
            'ba77a47634a0e99080ce3097d6d87b02b4904d80f4a809cac0124d31a2a0e829'
            '606624dc18235ca8b0cef113c65f1561e85f99ead4cfae08005e7439b18ffe32'
            '97184a6e90a682ae1726d57994e959d1a56cf066f7e5f23129d395d116b384e3'
            '1816172f86c5fe8f742d7b08fef250c351c1efef8e35f8da367fcf188ba6ac56'
            '0ddada23a1d060817b06a081d6f3fbb45a86dea9c0632d79f747c9a35a7a26b4'
            '63fbf5fb4845521772fdd3d699188f8cf30a99999ed639a66bdb1d236a14e5d4'
            'c5cbfb64eb7b19d6f1f1c1eb9c3278fcfbed8bfc482f8f36025cbdd3eef642a5'
            'a94a90b514105550e4e1a0502c1400d470d800fb137df4cf45f9a03fea224804')
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

  # Patch clang
  cd "${srcdir}"/clang
  apply_git_patch_with_msg 0102-Clang-Cygwin-Enable-few-conditions-that-are-shared-w.patch
  apply_git_patch_with_msg 0103-Clang-Cygwin-Enable-TLS.patch
  apply_git_patch_with_msg 0104-Clang-Cygwin-Fix-symbol-visibility-definition-138118.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.patch
  apply_git_patch_with_msg 0111-Clang-Driver-use-__cxa_atexit-by-default-on-Cygwin.-.patch
  apply_git_patch_with_msg 0112-hack-cygwin-define-_GLIBCXX_USE_CXX11_ABI-to-1-if-no.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
}

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
}
