#!/bin/mkpkg
# description: Complete LLVM toolchain (clang, lld, compiler-rt, libc++, libunwind)
# url: https://llvm.org/

name=llvm-toolchain
version=21.1.8
release=1

depends=(libffi zlib zstd libedit ncurses)
makedeps=(cmake ninja python perl musl libgmp libmpfr libmpc)

source=(
    https://ftp.gnu.org/gnu/gcc/gcc-14.2.0/gcc-14.2.0.tar.xz
    https://github.com/llvm/llvm-project/releases/download/llvmorg-$version/llvm-project-$version.src.tar.xz
)

build() {
    GCC_VERSION=14.2.0
    BOOTSTRAP=$SRC/bootstrap

    #################################
    # Bootstrap: GCC
    #################################
    mkdir -p gcc-build && cd gcc-build
    $SRC/gcc-$GCC_VERSION/configure \
        --prefix=$BOOTSTRAP \
        --enable-languages=c,c++ \
        --disable-nls \
        --disable-multilib \
        --disable-bootstrap \
        --disable-libsanitizer \
        --disable-libssp \
        --disable-werror \
        --with-system-zlib \
        --build=x86_64-unknown-linux-musl \
        --host=x86_64-unknown-linux-musl \
        --target=x86_64-unknown-linux-musl
    make -j$(nproc)
    make install
    cd $SRC

    mv llvm-project-$version.src llvm-project

    #################################
    # Stage 0: clang + lld (with GCC)
    #################################
    cmake -S llvm-project/llvm -B build-stage0 -G Ninja \
        -DCMAKE_BUILD_TYPE=Release \
        -DCMAKE_C_COMPILER=$BOOTSTRAP/bin/gcc \
        -DCMAKE_CXX_COMPILER=$BOOTSTRAP/bin/g++ \
        -DLLVM_ENABLE_PROJECTS="clang;lld" \
        -DLLVM_TARGETS_TO_BUILD="X86" \
        -DLLVM_HOST_TRIPLE=x86_64-unknown-linux-musl \
        -DLLVM_DEFAULT_TARGET_TRIPLE=x86_64-unknown-linux-musl \
        -DLLVM_BUILD_LLVM_DYLIB=ON \
        -DLLVM_LINK_LLVM_DYLIB=ON \
        -DLLVM_INCLUDE_TESTS=OFF \
        -DLLVM_INCLUDE_BENCHMARKS=OFF

    ninja -C build-stage0

    #################################
    # Stage 1: compiler-rt (standalone)
    #################################
    cmake -S llvm-project/compiler-rt -B build-rt -G Ninja \
        -DCMAKE_BUILD_TYPE=Release \
        -DCMAKE_INSTALL_PREFIX=$SRC/build-stage0/lib/clang/21 \
        -DCMAKE_C_COMPILER=$SRC/build-stage0/bin/clang \
        -DCMAKE_CXX_COMPILER=$SRC/build-stage0/bin/clang++ \
        -DCMAKE_C_FLAGS="--gcc-toolchain=$BOOTSTRAP" \
        -DCMAKE_CXX_FLAGS="--gcc-toolchain=$BOOTSTRAP" \
        -DCMAKE_C_COMPILER_TARGET=x86_64-unknown-linux-musl \
        -DCMAKE_CXX_COMPILER_TARGET=x86_64-unknown-linux-musl \
        -DCMAKE_MODULE_PATH="$SRC/llvm-project/cmake/Modules;$SRC/llvm-project/llvm/cmake/modules" \
        -DLLVM_CMAKE_DIR=$SRC/build-stage0/lib/cmake/llvm \
        -DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=ON \
        -DCOMPILER_RT_BUILD_BUILTINS=ON \
        -DCOMPILER_RT_BUILD_SANITIZERS=OFF \
        -DCOMPILER_RT_BUILD_XRAY=OFF \
        -DCOMPILER_RT_BUILD_GWP_ASAN=OFF \
        -DCOMPILER_RT_BUILD_MEMPROF=OFF \
        -DCOMPILER_RT_BUILD_PROFILE=OFF \
        -DCOMPILER_RT_BUILD_LIBFUZZER=OFF \
        -DCOMPILER_RT_BUILD_CTX_PROFILE=OFF \
        -DCOMPILER_RT_BUILD_ORC=OFF \
        -DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON \
        -DCOMPILER_RT_INCLUDE_TESTS=OFF

    ninja -C build-rt
    ninja -C build-rt install

    #################################
    # Stage 2: libunwind (standalone)
    #################################
    cmake -S llvm-project/runtimes -B build-unwind -G Ninja \
        -DCMAKE_BUILD_TYPE=Release \
        -DCMAKE_INSTALL_PREFIX=$SRC/stage0-sysroot/usr \
        -DCMAKE_C_COMPILER=$SRC/build-stage0/bin/clang \
        -DCMAKE_CXX_COMPILER=$SRC/build-stage0/bin/clang++ \
        -DCMAKE_C_FLAGS="--gcc-toolchain=$BOOTSTRAP" \
        -DCMAKE_CXX_FLAGS="--gcc-toolchain=$BOOTSTRAP" \
        -DLLVM_ENABLE_LLD=ON \
        -DLLVM_CMAKE_DIR=$SRC/build-stage0/lib/cmake/llvm \
        -DLLVM_ENABLE_RUNTIMES="libunwind" \
        -DLIBUNWIND_USE_COMPILER_RT=ON \
        -DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=OFF

    ninja -C build-unwind
    ninja -C build-unwind install

    #################################
    # Stage 3: libc++ (with libunwind)
    #################################
    cmake -S llvm-project/runtimes -B build-cxx -G Ninja \
        -DCMAKE_BUILD_TYPE=Release \
        -DCMAKE_INSTALL_PREFIX=$SRC/stage0-sysroot/usr \
        -DCMAKE_C_COMPILER=$SRC/build-stage0/bin/clang \
        -DCMAKE_CXX_COMPILER=$SRC/build-stage0/bin/clang++ \
        -DCMAKE_C_FLAGS="--gcc-toolchain=$BOOTSTRAP" \
        -DCMAKE_CXX_FLAGS="--gcc-toolchain=$BOOTSTRAP" \
        -DCMAKE_EXE_LINKER_FLAGS="-L$SRC/stage0-sysroot/usr/lib -lunwind" \
        -DCMAKE_SHARED_LINKER_FLAGS="-L$SRC/stage0-sysroot/usr/lib -lunwind" \
        -DLLVM_ENABLE_LLD=ON \
        -DLLVM_CMAKE_DIR=$SRC/build-stage0/lib/cmake/llvm \
        -DLLVM_HOST_TRIPLE=x86_64-unknown-linux-musl \
        -DLLVM_DEFAULT_TARGET_TRIPLE=x86_64-unknown-linux-musl \
        -DLLVM_ENABLE_RUNTIMES="libunwind;libcxxabi;libcxx" \
        -DLIBCXX_HAS_MUSL_LIBC=ON \
        -DLIBCXX_HAS_ATOMIC_LIB=OFF \
        -DLIBCXX_USE_COMPILER_RT=ON \
        -DLIBCXX_CXX_ABI=libcxxabi \
        -DLIBCXX_ENABLE_STATIC=ON \
        -DLIBCXXABI_USE_COMPILER_RT=ON \
        -DLIBCXXABI_USE_LLVM_UNWINDER=ON \
        -DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=OFF \
        -DLLVM_INCLUDE_TESTS=OFF

    ninja -C build-cxx cxx cxxabi
    ninja -C build-cxx install-cxx install-cxxabi

    #################################
    # Stage 4: final clang (pure libc++)
    # Minimal: clang, lld, runtimes only
    #################################
    export LD_LIBRARY_PATH=$SRC/stage0-sysroot/usr/lib

    # Stage 0 clang needs explicit flags to use lld and compiler-rt
    # -fPIC is required for shared library builds
    # --unwindlib=libunwind needed for runtimes that use unwind symbols
    STAGE4_CFLAGS="-fPIC -fuse-ld=lld --rtlib=compiler-rt -Qunused-arguments"
    STAGE4_CXXFLAGS="-fPIC -fuse-ld=lld --rtlib=compiler-rt --unwindlib=libunwind -stdlib=libc++ -I$SRC/stage0-sysroot/usr/include/c++/v1 -Qunused-arguments"
    STAGE4_LDFLAGS="-fuse-ld=lld -L$SRC/stage0-sysroot/usr/lib -lunwind -Wl,-rpath,$SRC/stage0-sysroot/usr/lib"

    cmake -S llvm-project/llvm -B build-final -G Ninja -Wno-dev \
        -DCMAKE_BUILD_TYPE=Release \
        -DCMAKE_INSTALL_PREFIX=/usr \
        -DCMAKE_C_COMPILER=$SRC/build-stage0/bin/clang \
        -DCMAKE_CXX_COMPILER=$SRC/build-stage0/bin/clang++ \
        -DCMAKE_C_FLAGS="$STAGE4_CFLAGS" \
        -DCMAKE_CXX_FLAGS="$STAGE4_CXXFLAGS" \
        -DCMAKE_EXE_LINKER_FLAGS="$STAGE4_LDFLAGS" \
        -DCMAKE_SHARED_LINKER_FLAGS="$STAGE4_LDFLAGS" \
        -DLLVM_ENABLE_LLD=ON \
        -DLLVM_ENABLE_PROJECTS="clang;lld" \
        -DLLVM_ENABLE_RUNTIMES="compiler-rt;libunwind;libcxxabi;libcxx" \
        -DLLVM_TARGETS_TO_BUILD="X86" \
        -DLLVM_HOST_TRIPLE=x86_64-unknown-linux-musl \
        -DLLVM_DEFAULT_TARGET_TRIPLE=x86_64-unknown-linux-musl \
        -DLLVM_ENABLE_RTTI=ON \
        -DLLVM_ENABLE_FFI=ON \
        -DLLVM_ENABLE_ZLIB=ON \
        -DLLVM_ENABLE_ZSTD=ON \
        -DLLVM_ENABLE_LIBEDIT=ON \
        -DLLVM_BUILD_LLVM_DYLIB=ON \
        -DLLVM_LINK_LLVM_DYLIB=ON \
        -DLLVM_INSTALL_BINUTILS_SYMLINKS=ON \
        -DLLVM_INCLUDE_TESTS=OFF \
        -DLLVM_INCLUDE_BENCHMARKS=OFF \
        -DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=OFF \
        -DLLVM_RUNTIME_LIBRARY_DIR=$SRC/stage0-sysroot/usr/lib \
        -DCLANG_DEFAULT_CXX_STDLIB=libc++ \
        -DCLANG_DEFAULT_RTLIB=compiler-rt \
        -DCLANG_DEFAULT_UNWINDLIB=libunwind \
        -DCLANG_DEFAULT_LINKER=lld \
        -DCLANG_LINK_CLANG_DYLIB=ON \
        -DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON \
        -DCOMPILER_RT_BUILD_BUILTINS=ON \
        -DCOMPILER_RT_BUILD_SANITIZERS=OFF \
        -DCOMPILER_RT_BUILD_XRAY=OFF \
        -DCOMPILER_RT_BUILD_LIBFUZZER=OFF \
        -DCOMPILER_RT_BUILD_PROFILE=OFF \
        -DCOMPILER_RT_BUILD_MEMPROF=OFF \
        -DCOMPILER_RT_BUILD_GWP_ASAN=OFF \
        -DCOMPILER_RT_BUILD_CTX_PROFILE=OFF \
        -DCOMPILER_RT_BUILD_ORC=OFF \
        -DLIBCXX_HAS_MUSL_LIBC=ON \
        -DLIBCXX_HAS_ATOMIC_LIB=OFF \
        -DLIBCXX_USE_COMPILER_RT=ON \
        -DLIBCXX_CXX_ABI=libcxxabi \
        -DLIBCXX_ENABLE_STATIC=ON \
        -DLIBCXX_ENABLE_SHARED=ON \
        -DLIBCXXABI_USE_COMPILER_RT=ON \
        -DLIBCXXABI_USE_LLVM_UNWINDER=ON \
        -DLIBCXXABI_ENABLE_SHARED=ON \
        -DLIBUNWIND_USE_COMPILER_RT=ON \
        -DLIBUNWIND_ENABLE_SHARED=ON

    ninja -C build-final
    DESTDIR=$PKG ninja -C build-final install

    ln -sf clang   $PKG/usr/bin/cc
    ln -sf clang++ $PKG/usr/bin/c++
    ln -sf lld     $PKG/usr/bin/ld
    ln -sf clang   $PKG/usr/bin/ccp
}

# vim: filetype=sh
