# Copyright 1999-2026 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 EAPI=8 PYTHON_COMPAT=( python3_{12..14} ) inherit check-reqs cmake flag-o-matic python-any-r1 # AMD retired the rocm-* release line at rocm-7.2.4 (2026-05-28); everything # since is tagged therock-. This is the SAME source archive that # dev-libs/rocm-device-libs, dev-libs/rocm-comgr and dev-util/hipcc already # fetch -- they unpack the amd/ subdirectory, we unpack the compiler itself -- # so MY_P must stay byte-identical to theirs to share one DIST entry. MY_P=llvm-project-therock-$(ver_cut 1-2) DESCRIPTION="AMD's LLVM fork, as shipped with ROCm" HOMEPAGE="https://github.com/ROCm/llvm-project" SRC_URI="https://github.com/ROCm/llvm-project/archive/therock-$(ver_cut 1-2).tar.gz -> ${MY_P}.tar.gz" S="${WORKDIR}/${MY_P}/llvm" LICENSE="Apache-2.0-with-LLVM-exceptions UoI-NCSA BSD public-domain rc" # Subslot tracks the ROCm release, matching the rest of the split stack: this # compiler is only meaningful paired with the ROCm it shipped with. SLOT="0/$(ver_cut 1-2)" KEYWORDS="~amd64" IUSE="debug" # The point of this package is to be a device-code compiler, so nothing here # is a runtime dependency of anything except the ROCm build tooling. RDEPEND=" dev-libs/libxml2:= virtual/zlib:= app-arch/zstd:= dev-libs/rocm-device-libs:${SLOT} " DEPEND="${RDEPEND}" BDEPEND=" ${PYTHON_DEPS} app-alternatives/ninja dev-build/cmake " # ROCm's LLVM is a full compiler build. Scoped down hard in src_configure # (two targets, three projects, no tests/docs/bindings), but it is still LLVM. # Numbers measured on the first build; revisit if the project list grows. CHECKREQS_DISK_BUILD="30G" pkg_pretend() { [[ ${MERGE_TYPE} == binary ]] && return check-reqs_pkg_pretend } pkg_setup() { [[ ${MERGE_TYPE} == binary ]] && return check-reqs_pkg_setup python-any-r1_pkg_setup } src_unpack() { # The archive carries the whole llvm-project monorepo (~263 MB compressed, # every subproject including flang, mlir, lldb and libsycl). Extract only # what the compiler build reads: cmake/ for the shared modules, llvm/ as # S=, and the three projects enabled below. This turns a multi-GB unpack # into a fraction of it. # # Two of these are needed despite their PROJECT being disabled, both found # by build failure rather than inspection -- verified 2026-08-29: # libc/ llvm's CMakeLists does an unconditional # include(FindLibcCommonUtils) and FATAL_ERRORs without the # header-only llvm-libc-common-utilities target from # libc/src/__support. # openmp/ AMD-fork-specific: clang/lib/CodeGen/CGEmitEmissaryExec.cpp # hard-includes "../../openmp/device/include/EmissaryIds.h" for # AMD's Emissary offload feature. Unconditional, so it is needed # even with the openmp project off. # libunwind/include/mach-o/ # lld builds its MachO backend unconditionally and takes # from libunwind's include # tree (lld/MachO/CMakeLists.txt adds # ${LLVM_MAIN_SRC_DIR}/../libunwind/include). ::gentoo's # llvm-core/lld extracts exactly this path for the same reason. # The mlir/ and libunwind/ references under clang/ are ClangIR-only # (tools/cir-*, unittests/CIR) and stay unreachable while CLANG_ENABLE_CIR # is off, so the rest of libunwind is deliberately not extracted. local want=( "${MY_P}/cmake" "${MY_P}/llvm" "${MY_P}/clang" "${MY_P}/lld" "${MY_P}/libc" "${MY_P}/openmp" "${MY_P}/compiler-rt" "${MY_P}/libunwind/include/mach-o" "${MY_P}/runtimes" "${MY_P}/third-party" ) ebegin "Unpacking the compiler subset from ${MY_P}.tar.gz" tar -x -z -o -f "${DISTDIR}/${MY_P}.tar.gz" "${want[@]}" || die eend ${?} } src_configure() { local mycmakeargs=( # AMD installs its compiler under /lib/llvm. We deliberately do # NOT use /usr/lib/llvm/, which is Gentoo's slot root for # llvm-core/llvm -- a private prefix is what keeps this package from # competing with the system LLVM at all. -DCMAKE_INSTALL_PREFIX="${EPREFIX}/usr/lib/${PN}" # AMDGPU is the entire reason this package exists; X86 is needed for # the host side of any HIP compile. -DLLVM_TARGETS_TO_BUILD="AMDGPU;X86" -DLLVM_ENABLE_PROJECTS="clang;lld" # compiler-rt supplies libclang_rt.builtins, which clang links into # every HIP target; without it consumers fail at link time with # "libclang_rt.builtins.a ... missing and no known rule to make it". -DLLVM_ENABLE_RUNTIMES="compiler-rt" # Match the system LLVM's packaging shape so consumers that resolve # components (e.g. llvm_map_components_to_libnames) get the dylib # rather than per-component archives. -DLLVM_BUILD_LLVM_DYLIB=ON -DLLVM_LINK_LLVM_DYLIB=ON # LLVM refuses BUILD_SHARED_LIBS together with LLVM_LINK_LLVM_DYLIB # ("we recommend disabling BUILD_SHARED_LIBS"); the two are different # strategies for the same goal. The single libLLVM.so is the one we # want, matching how llvm-core/llvm is built. -DBUILD_SHARED_LIBS=OFF -DLLVM_ENABLE_ZLIB=FORCE_ON -DLLVM_ENABLE_ZSTD=FORCE_ON -DLLVM_ENABLE_LIBXML2=FORCE_ON # Detected automagically otherwise, putting an undeclared # DT_NEEDED on libedit.so.0 into libLLVM. Nothing here is used # interactively -- this compiler exists to be driven by # rocm_use_clang() -- so turn it off rather than take the # dependency. verified 2026-08-30 by readelf on libLLVM.so. -DLLVM_ENABLE_LIBEDIT=OFF # Nothing here is consumed; skip it all to keep the build bounded. -DLLVM_BUILD_TESTS=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_BENCHMARKS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_ENABLE_OCAMLDOC=OFF -DLLVM_ENABLE_BINDINGS=OFF -DLLVM_ENABLE_TERMINFO=OFF -DLLVM_INSTALL_UTILS=OFF # Explicit, like llvm-core/llvm. Necessary but NOT sufficient on its # own -- see the append-cflags below. -DLLVM_ENABLE_ASSERTIONS=$(usex debug) -DPython3_EXECUTABLE="${PYTHON}" -Wno-dev ) if ! use debug; then # LLVM_ENABLE_ASSERTIONS=no only stops LLVM from UN-defining NDEBUG; # it counts on CMake's own CMAKE_CXX_FLAGS_RELEASE to DEFINE it. But # cmake.eclass blanks the per-config flag variables so they cannot # override user CXXFLAGS, so nothing defines NDEBUG and every assert() # in LLVM stays live -- `clang-23 --version` then reports # "Build config: +assertions" despite the option being off. # # That is not cosmetic. sci-ml/caffe2 aborts building rocPRIM's # merge-sort kernels for gfx1150: # # clang-23: llvm/lib/CodeGen/LiveRegUnits.cpp:45: # void llvm::LiveRegUnits::stepBackward(...): Assertion failed # ... Running pass 'SI optimize exec mask operations' # # As with sci-libs/hipBLASLt and sci-libs/composable-kernel, this # aligns the build config with AMD's shipped Release compiler; it does # not address why that invariant is violated in the first place. AMD's # own binaries take the same code path without aborting. If ROCm ever # produces visibly wrong kernels, revisit this rather than assume the # codegen is sound. verified 2026-08-30. append-cflags "-DNDEBUG" append-cxxflags "-DNDEBUG" mycmakeargs+=( -DCMAKE_BUILD_TYPE=Release ) fi cmake_src_configure } src_install() { cmake_src_install # rocm.eclass's rocm_use_clang() does # export CC="${hipclangpath}/${CHOST}-clang" # export CXX="${hipclangpath}/${CHOST}-clang++" # i.e. it expects Gentoo's CHOST-prefixed wrapper names, which # llvm-core/clang provides as symlinks. AMD's build installs only the # unprefixed clang/clang++ (plus its own amdclang* aliases), so without # these every ROCm library configured through rocm_use_clang fails with # "CMAKE_CXX_COMPILER ... is not a full path to an existing compiler tool". # Mirror llvm-core/clang's layout. verified 2026-08-29. local t for t in clang clang++; do [[ -e ${ED}/usr/lib/${PN}/bin/${t} ]] || die "AMD LLVM did not install bin/${t}; wrapper names need re-checking" dosym "${t}" "/usr/lib/${PN}/bin/${CHOST}-${t}" done # Let this clang find dev-libs/rocm-device-libs. Clang looks for the ROCm # device bitcode under /lib/amdgcn/bitcode; # rocm-device-libs installs the real files to /usr/lib/amdgcn/bitcode and # symlinks them into the SYSTEM clang's resource dir only, so AMD's clang # otherwise fails every HIP compile with "cannot find ROCm device # library". # # Note the subdirectory differs by build: Gentoo's llvm sets # LLVM_LIBDIR_SUFFIX so its resource dir uses lib64/amdgcn, while this # build uses the default and wants lib/amdgcn. Glob the version component # rather than hardcoding the clang major. verified 2026-08-29. local rd found= for rd in "${ED}"/usr/lib/${PN}/lib/clang/*; do [[ -d ${rd} ]] || continue dosym -r /usr/lib/amdgcn "${rd#"${ED}"}/lib/amdgcn" found=1 done [[ -n ${found} ]] || die "no clang resource dir under /usr/lib/${PN}/lib/clang; device-lib symlink not placed" # No env.d and no symlinks into /usr/bin. This compiler must be reachable # only when something asks for it explicitly -- shadowing the system # clang would be a much worse outcome than the problem it solves. The # consumer-side hook is dev-util/hipcc[amd-llvm], which makes # `hipconfig --hipclangpath` report the path below; rocm.eclass's # rocm_use_clang() then routes every ROCm library build through it. # clang's scan-build ships a man page into the shared /usr/share/man, # which breaks the "everything stays in the private prefix" property and # advertises a tool that is deliberately not in PATH. Drop it. rm -rf "${ED}/usr/share/man" || die elog "AMD's LLVM is installed to ${EPREFIX}/usr/lib/${PN}" elog elog "It is deliberately NOT in PATH and does not shadow llvm-core/clang." elog "To build the ROCm math libraries with it, enable USE=amd-llvm on" elog "dev-util/hipcc; rocm.eclass picks it up automatically from" elog "\`hipconfig --hipclangpath\`." }