Full Host Build¶
Note
Fullbuild requires running headergen, which is a python program that depends on pyyaml. The minimum versions are listed on the Generating Public and Internal headers page, as well as additional information.
Standard Building and Testing¶
Note
If your build fails with an error saying the compiler can’t find
<asm/unistd.h> or similar then you’re probably missing the symlink from
/usr/include/asm to /usr/include/<HOST TRIPLE>/asm. Installing the
gcc-multilib package creates this symlink, or you can do it manually with
this command:
sudo ln -s /usr/include/<HOST TRIPLE>/asm /usr/include/asm
(your host triple will probably be similar to x86_64-linux-gnu)
For basic development, such as adding new functions or fixing bugs, you can build and test the libc directly without setting up a full sysroot. This approach is faster and sufficient for most contributors.
To configure the build, create a build directory and run cmake:
cmake \
-B build \
-S runtimes \
-G Ninja \
-DCMAKE_C_COMPILER=clang \
-DCMAKE_CXX_COMPILER=clang++ \
-DLLVM_ENABLE_RUNTIMES="libc;compiler-rt" \
-DLLVM_LIBC_FULL_BUILD=ON \
-DCMAKE_BUILD_TYPE=Debug \
-DLLVM_LIBC_INCLUDE_SCUDO=ON \
-DCOMPILER_RT_BUILD_SCUDO_STANDALONE_WITH_LLVM_LIBC=ON \
-DCOMPILER_RT_BUILD_GWP_ASAN=OFF \
-DCOMPILER_RT_SCUDO_STANDALONE_BUILD_SHARED=OFF \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
-DLLVM_ENABLE_SPHINX=ON -DLIBC_INCLUDE_DOCS=ON \
-DLIBC_CMAKE_VERBOSE_LOGGING=ON
After configuring the build, you can build the libc, math library, and run the tests with the following command:
ninja -C build libc libm check-libc
To run a specific unit test for a function, you can target it directly using its full name:
ninja -C build libc.test.src.<HEADER>.<FUNCTION>_test.__unit__
For example, to run the test for isalpha in ctype.h:
ninja -C build libc.test.src.ctype.isalpha_test.__unit__
Building Documentation¶
If you have Sphinx installed, you can build the libc documentation locally. The
build configuration above already includes the necessary flags
(-DLLVM_ENABLE_SPHINX=ON -DLIBC_INCLUDE_DOCS=ON).
To generate the HTML documentation:
ninja -C build docs-libc-html
The generated documentation will be available in the docs/libc/html directory
within your build folder.
Building a Simple Sysroot¶
Warning
The LLVM libc is missing many critical functions needed to build non-trivial applications. If you are not currently working on porting the libc, we recommend sticking with your system libc. However, ignoring warnings like this are how most of us got into this business. So: Speak friend and enter.
This document describes how to set up a simple sysroot and a compiler that uses it from scratch. These are not full cross-compilation instructions. We make a few assumptions:
The host and target are the same architecture and OS. For example, building a Linux x86-64 libc on a Linux x86-64 host.
The host has a working and recent Clang toolchain. Clang 21 has been tested.
Your container is using Debian Testing or a derived distribution. Other distributions likely work but the package names and paths may differ.
You have root access to your machine to set up the compiler wrapper.
For more comprehensive instructions on setting up a sysroot, see the official LLVM guide.
Step 1: Preparation¶
First, set up the environment variables for your sysroot path and the major version of your host Clang.
SYSROOT=$(readlink -f ~/sysroot)
Step 2: Linux Headers¶
Next, install the Linux kernel headers into your sysroot. For this guide, we’ll
copy the headers from the host system’s /usr/include directory. This
includes linux, asm-generic, and the architecture-specific asm
headers.
# Create the include directory
mkdir -p $SYSROOT/usr/include
# Copy the header directories
cp -R /usr/include/linux $SYSROOT/usr/include/
cp -R /usr/include/asm-generic $SYSROOT/usr/include/
# Use -L to dereference the asm symlink and copy the actual files
cp -R -L /usr/include/asm $SYSROOT/usr/include/
Note
For a more production-ready sysroot, you would typically download a specific
kernel version and install the headers using make headers_install
configured for the target architecture and installation path.
Step 3: Build and Install Runtimes¶
Now, configure the build for LLVM libc and compiler-rt. We’re building with
llvm instead of runtimes because we need to install the
clang-resource-headers that provide stdarg.h, stddef.h and others.
cmake \
-S llvm \
-B build-runtimes \
-G Ninja \
-DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=OFF \
-DCMAKE_INSTALL_PREFIX=$SYSROOT/usr \
-DLLVM_ENABLE_PROJECTS="clang" \
-DLLVM_ENABLE_RUNTIMES="libc;compiler-rt" \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_LIBC_FULL_BUILD=ON \
-DLIBC_INCLUDE_DOCS=OFF \
-DLLVM_LIBC_INCLUDE_SCUDO=ON \
-DCOMPILER_RT_BUILD_SCUDO_STANDALONE_WITH_LLVM_LIBC=ON \
-DCOMPILER_RT_BUILD_GWP_ASAN=OFF \
-DCOMPILER_RT_SCUDO_STANDALONE_BUILD_SHARED=OFF \
-DCOMPILER_RT_BUILD_BUILTINS:BOOL=TRUE \
-DCOMPILER_RT_BUILD_CRT:BOOL=TRUE \
-DCOMPILER_RT_BUILD_GWP_ASAN:BOOL=FALSE
After configuring, build and install the necessary components:
ninja -C build-runtimes install-clang-resource-headers install-libc install-compiler-rt install-builtins
Step 4: Configure the Compiler Wrapper¶
To make using the new toolchain easier, you can create a Clang configuration file. This allows you to avoid passing long command line arguments every time you compile a program.
Identify the directory where your Clang binary is located:
CLANG_DIR=$(dirname $(readlink -f /usr/bin/clang))
Create a symlink to
clangnamedllvm-libc-clangin that directory:
sudo ln -sf $CLANG_DIR/clang /usr/bin/llvm-libc-clang
Create the configuration file in the same directory. Clang automatically looks for a file named
<executable-name>.cfgin the same directory as the executable. Use the following command to generate it with your environment variables:
CLANG_VERSION=$(build-runtimes/bin/clang -dumpversion | cut -d. -f1)
cat <<EOF | sudo tee $CLANG_DIR/llvm-libc-clang.cfg
--target=x86_64-unknown-linux-llvm
--sysroot=$SYSROOT
-resource-dir=$SYSROOT/usr/lib/clang/$CLANG_VERSION
--rtlib=compiler-rt
--unwindlib=none
-static
EOF
Step 5: Verification¶
You can now use your newly built toolchain by running your wrapper.
// hello.c
#include <stdio.h>
int main() {
printf("Hello, World!\n");
return 0;
}
Compile and run the example:
llvm-libc-clang hello.c
./a.out