[libc] Rewrite "Full Host Build" instructions (#180439)

This commit restructures the full_host_build.rst documentation to better
serve two use cases:

1. Standard Building and Testing: Add a new introductory section with
simplified instructions for local development. This covers basic build
configuration, building/testing without a full sysroot, and
documentation generation.

2. Building a Sysroot: Reorganize the comprehensive sysroot setup
instructions into a clear 5-step guide:
   - Step 1: Preparation (environment variables)
   - Step 2: Linux Headers (copying headers into sysroot)
- Step 3: Build and Install Runtimes (cmake configuration and ninja
build)
   - Step 4: Configure the Compiler Wrapper (creating clang config file)
   - Step 5: Verification (testing with sample C program)

Key improvements:
- Restructure content to lead with simpler development workflow
- Replace bootstrapping build instructions with clearer sysroot
instructions
- Fix typo: "non-triivial" -> "non-trivial"
- Remove directory changes that can be confusing. All commands are run
from the root of the llvm tree
- Improve code block formatting and add complete working examples
- Make it easy to cut and paste shell commands
- Simplify "Hello, World!" example
- Simplify and clarify assumptions and requirements
- Remove obsolete notes about C++ standard library support

Tested:
 * Built runtimes build and tests
 * Built sysroot and verified with sample C program
 * Verified document builds and looks right in VSCode browser
This commit is contained in:
Jeff Bailey 2026-02-12 07:54:34 +00:00 committed by GitHub
parent 664663cbbf
commit aa0e429576
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -13,23 +13,11 @@ Full Host Build
pyyaml. The minimum versions are listed on the :ref:`header_generation`
page, as well as additional information.
In this document, we will present a recipe to build the full libc for the host.
When we say *build the libc for the host*, the goal is to build the libc for
the same system on which the libc is being built. First, we will explain how to
build for developing LLVM-libc, then we will explain how to build LLVM-libc as
part of a complete toolchain.
Configure the build for development
===================================
Below is the list of commands for a simple recipe to build LLVM-libc for
development. In this we've set the Ninja generator, set the build type to
"Debug", and enabled the Scudo allocator. This build also enables generating the
documentation and verbose cmake logging, which are useful development features.
Standard Building and Testing
=============================
.. note::
if your build fails with an error saying the compiler can't find
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
@ -37,12 +25,17 @@ documentation and verbose cmake logging, which are useful development features.
``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``:
.. code-block:: sh
$> cd llvm-project # The llvm-project checkout
$> mkdir build
$> cd build
$> cmake ../runtimes \
cmake \
-B build \
-S runtimes \
-G Ninja \
-DCMAKE_C_COMPILER=clang \
-DCMAKE_CXX_COMPILER=clang++ \
@ -57,162 +50,186 @@ documentation and verbose cmake logging, which are useful development features.
-DLLVM_ENABLE_SPHINX=ON -DLIBC_INCLUDE_DOCS=ON \
-DLIBC_CMAKE_VERBOSE_LOGGING=ON
Build and test
==============
After configuring the build with the above ``cmake`` command, one can build test
libc with the following command:
After configuring the build, you can build the libc, math library, and run the
tests with the following command:
.. code-block:: sh
$> ninja libc libm check-libc
To build the docs run this 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:
.. code-block:: sh
$> ninja docs-libc-html
ninja -C build libc.test.src.<HEADER>.<FUNCTION>_test.__unit__
To run a specific test, use the following:
For example, to run the test for ``isalpha`` in ``ctype.h``:
.. code-block:: sh
$> ninja libc.test.src.<HEADER>.<FUNCTION>_test.__unit__
$> ninja libc.test.src.ctype.isalpha_test.__unit__ # EXAMPLE
ninja -C build libc.test.src.ctype.isalpha_test.__unit__
Configure the complete toolchain build
======================================
Building Documentation
======================
For a complete toolchain we recommend creating a *sysroot* (see the documentation
of the ``--sysroot`` option here:
`<https://gcc.gnu.org/onlinedocs/gcc/Directory-Options.html>`_) which includes
not only the components of LLVM's libc, but also a full LLVM only toolchain
consisting of the `clang <https://clang.llvm.org/>`_ compiler, the
`lld <https://lld.llvm.org/>`_ linker and the
`compiler-rt <https://compiler-rt.llvm.org/>`_ runtime libraries. LLVM-libc is
not quite complete enough to allow using and linking a C++ application against
a C++ standard library (like libc++). Hence, we do not include
`libc++ <https://libcxx.llvm.org/>`_ in the sysroot.
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``).
.. note:: When the libc is complete enough, we should be able to include
`libc++ <https://libcxx.llvm.org/>`_, libcxx-abi and libunwind in the
LLVM only toolchain and use them to build and link C++ applications.
To generate the HTML documentation:
Below is the cmake command for a bootstrapping build of LLVM. This will build
clang and lld with the current system's toolchain, then build compiler-rt and
LLVM-libc with that freshly built clang. This ensures that LLVM-libc can take
advantage of the latest clang features and optimizations.
.. code-block:: sh
This build also uses Ninja as cmake's generator, and sets lld and compiler-rt as
the default for the fresh clang. Those settings are recommended, but the build
should still work without them. The compiler-rt options are required for
building `Scudo <https://llvm.org/docs/ScudoHardenedAllocator.html>`_ as the
allocator for LLVM-libc.
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 <https://llvm.org/docs/HowToCrossCompileLLVM.html#setting-up-a-sysroot>`_.
Step 1: Preparation
-------------------
First, set up the environment variables for your sysroot path and the major
version of your host Clang.
.. code-block:: sh
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.
.. code-block:: sh
# 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::
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/<TARGET TRIPLE>/asm``. Installing the
``gcc-multilib`` package creates this symlink, or you can do it manually with
this command:
``sudo ln -s /usr/include/<TARGET TRIPLE>/asm /usr/include/asm``
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.
.. code-block:: sh
$> cd llvm-project # The llvm-project checkout
$> mkdir build
$> cd build
$> SYSROOT=/path/to/sysroot # Remember to set this!
$> cmake ../llvm \
-G Ninja \
-DLLVM_ENABLE_PROJECTS="clang;lld" \
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 \
-DCMAKE_C_COMPILER=clang \
-DCMAKE_CXX_COMPILER=clang++ \
-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 \
-DCLANG_DEFAULT_LINKER=lld \
-DCLANG_DEFAULT_RTLIB=compiler-rt \
-DCMAKE_INSTALL_PREFIX=$SYSROOT
-DCOMPILER_RT_BUILD_BUILTINS:BOOL=TRUE \
-DCOMPILER_RT_BUILD_CRT:BOOL=TRUE \
-DCOMPILER_RT_BUILD_GWP_ASAN:BOOL=FALSE
Build and install
=================
.. TODO: add this warning to the cmake
.. warning::
Running these install commands without setting a ``$SYSROOT`` will install
them into your system include path, which may break your system. If you're
just trying to develop libc, then just run ``ninja check-libc`` to build the
libc and run the tests. If you've already accidentally installed the headers,
you may need to delete them from ``/usr/local/include``.
After configuring the build with the above ``cmake`` command, one can build and
install the toolchain with
After configuring, build and install the necessary components:
.. code-block:: sh
$> ninja install-clang install-builtins install-compiler-rt \
install-core-resource-headers install-libc install-lld
ninja -C build-runtimes install-clang-resource-headers install-libc install-compiler-rt install-builtins
or
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.
1. Identify the directory where your Clang binary is located:
.. code-block:: sh
$> ninja install
CLANG_DIR=$(dirname $(readlink -f /usr/bin/clang))
Once the above command completes successfully, the ``$SYSROOT`` directory you
have specified with the CMake configure step above will contain a full LLVM-only
toolchain with which you can build practical/real-world C applications. See
`<https://github.com/llvm/llvm-project/tree/main/libc/examples>`_ for examples
of how to start using this new toolchain.
Linux Headers
=============
If you are using the full libc on Linux, then you will also need to install
Linux headers in your sysroot. Let's build them from source.
2. Create a symlink to ``clang`` named ``llvm-libc-clang`` in that directory:
.. code-block:: sh
$> git clone --depth=1 git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git /tmp/linux
$> make LLVM=1 INSTALL_HDR_PATH=/path/to/sysroot -C /tmp/linux headers_install
sudo ln -sf $CLANG_DIR/clang /usr/bin/llvm-libc-clang
The headers can be built to target non-host architectures by adding the
``ARCH={arm|arm64|i386}`` to the above invocation of ``make``.
Using your newly built libc
===========================
You can now use your newly built libc nearly like you would use any compiler
invocation:
3. Create the configuration file in the same directory. Clang automatically looks
for a file named ``<executable-name>.cfg`` in the same directory as the
executable. Use the following command to generate it with your environment
variables:
.. code-block:: sh
$> /path/to/sysroot/bin/clang -static main.c
CLANG_VERSION=$(build-runtimes/bin/clang -dumpversion | cut -d. -f1)
.. warning::
Because the libc does not yet support dynamic linking, the -static parameter
must be added to all clang invocations.
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 make sure you're using the newly built toolchain by trying out features
that aren't yet supported by the system toolchain, such as fixed point. The
following is an example program that demonstrates the difference:
You can now use your newly built toolchain by running your wrapper.
.. code-block:: C
// $ $SYSROOT/bin/clang example.c -static -ffixed-point --sysroot=$SYSROOT
// hello.c
#include <stdio.h>
int main() {
printf("Hello, World!\n%.9f\n%.9lK\n",
4294967295.000000001,
4294967295.000000001ulK);
printf("Hello, World!\n");
return 0;
}
Compile and run the example:
.. code-block:: sh
llvm-libc-clang hello.c
./a.out