# Copyright 1999-2026 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 EAPI=8 PYTHON_COMPAT=( python3_{12..15} ) inherit cmake llvm.org python-any-r1 toolchain-funcs DESCRIPTION="LLVM's implementation of the C standard library" HOMEPAGE="https://libc.llvm.org/" # getent is the one Alpine wrote for musl, the same file sys-libs/musl installs. # llvm.org_set_globals adds the LLVM sources to this further down. GETENT_COMMIT="93a08815f8598db442d8b766b463d0150ed8e2ab" GETENT_FILE="musl-getent-${GETENT_COMMIT}.c" SRC_URI=" https://gitlab.alpinelinux.org/alpine/aports/-/raw/${GETENT_COMMIT}/main/musl/getent.c -> ${GETENT_FILE} " # getent is BSD-2. LICENSE="Apache-2.0-with-LLVM-exceptions || ( UoI-NCSA MIT ) BSD-2" SLOT="${LLVM_MAJOR}" IUSE="test" RESTRICT="!test? ( test )" # A runtimes build takes its cmake modules from the tree it is building, so # there is nothing here for an installed LLVM of the same slot to provide. # Any clang recent enough to build the tree will do, and need not match: the # 24 series builds with 23. BDEPEND=" || ( llvm-core/clang:${LLVM_MAJOR} >=llvm-core/clang-23:* ) ${PYTHON_DEPS} " DEPEND="virtual/os-headers" # The libc is built through the runtimes directory rather than on its own, so # that scudo can be taken from compiler-rt in the same configure. LLVM_COMPONENTS=( libc runtimes cmake llvm/cmake compiler-rt third-party/siphash ) llvm.org_set_globals pkg_pretend() { # This is the C library of the system it goes on: it owns the headers in # /usr/include and installs a loader and libc.so of its own. On a system # already running glibc or musl it would take their place, so it refuses. [[ ${MERGE_TYPE} == buildonly ]] && return local lib for lib in "${EROOT}"/{,usr/}lib{,64}/{libc.so.6,ld-musl-*.so.1}; do [[ -e ${lib} ]] && die "${lib#"${EROOT}"} belongs to another C library, which ${PN} would replace" done } pkg_setup() { # The library is written for clang: it uses builtins and attributes GCC # does not have, and the headers it generates are meant for clang. tc-is-clang || die "llvm-libc must be built with clang, set CC=clang" python-any-r1_pkg_setup } src_configure() { CMAKE_USE_DIR=${WORKDIR}/runtimes local libdir=$(get_libdir) local mycmakeargs=( -DLLVM_ENABLE_RUNTIMES="libc;compiler-rt" # A full build owns the headers as well as the library, which is the # only way it can be the C library of the system rather than a set of # functions layered over another one. -DLLVM_LIBC_FULL_BUILD=ON -DLIBC_ENABLE_SHARED=ON # scudo is the allocator. Without it malloc and the rest are only # declared, and nothing implements them. -DLLVM_LIBC_INCLUDE_SCUDO=ON # scudo is compiled against the headers of the libc it goes into, not # those of whatever C library the build machine has. -DCOMPILER_RT_BUILD_SCUDO_STANDALONE_WITH_LLVM_LIBC=ON # The libraries, startup files and loader go in the platform's libdir # like any other C library, and not in a directory per target. -DLLVM_LIBDIR_SUFFIX=${libdir#lib} -DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=OFF # The entrypoints behind this are the ones which are implemented but # not yet in the default list, which is most of what a distribution # needs from it today. -DLLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS=ON -DLLVM_INCLUDE_TESTS=$(usex test) # Of compiler-rt, only scudo is wanted. -DCOMPILER_RT_SANITIZERS_TO_BUILD=scudo_standalone -DCOMPILER_RT_BUILD_GWP_ASAN=OFF -DCOMPILER_RT_BUILD_BUILTINS=OFF -DCOMPILER_RT_BUILD_XRAY=OFF -DCOMPILER_RT_BUILD_LIBFUZZER=OFF -DCOMPILER_RT_BUILD_PROFILE=OFF -DCOMPILER_RT_BUILD_CTX_PROFILE=OFF -DCOMPILER_RT_BUILD_MEMPROF=OFF -DCOMPILER_RT_BUILD_ORC=OFF ) cmake_src_configure } src_compile() { # The library, its loader, startup files and headers, and nothing else. # Configuring scudo also puts compiler-rt's sanitizer_common into the # default target, and that does not build against this library's headers. # The empty libdl, libpthread and the rest are made along with libc. cmake_build libc libc-shared libm libm-shared libmvec libmvec-shared \ libc-startup libc-loader generate-libc-headers # getent is built against the library just built rather than the one # installed, which may be too old to have everything it calls. local libc_build=${BUILD_DIR}/libc "$(tc-getCC)" ${CPPFLAGS} -isystem "${libc_build}/include" ${CFLAGS} \ ${LDFLAGS} -L"${libc_build}/lib" -o "${T}"/getent \ "${DISTDIR}/${GETENT_FILE}" || die "building getent failed" } src_test() { cmake_build check-libc } src_install() { # Only the library and its headers. compiler-rt is configured alongside it # for scudo, which ends up inside libc.so, and a plain install would put # compiler-rt's own files into clang's resource directory as well. local component for component in libc libc-headers; do DESTDIR="${D}" cmake --install "${BUILD_DIR}" --component "${component}" || die "installing ${component} failed" done # The loader looks under the directories /etc/ld-llvm-libc-.path # lists, and env-update keeps ld.so.conf current from env.d, so the one # file is a link to the other. local arch=${CHOST%%-*} [[ ${arch} == riscv* ]] && arch=riscv dosym ld.so.conf "/etc/ld-llvm-libc-${arch}.path" dobin "${T}"/getent }