[libc-commits] [libc] [libc][docs][NFC] Document cross-compilation testing with QEMU (PR #188838)

via libc-commits libc-commits at lists.llvm.org
Thu Mar 26 13:54:25 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libc

Author: Jeff Bailey (kaladron)

<details>
<summary>Changes</summary>

Added a "Building and Testing with an Emulator" section to full_cross_build.rst using riscv64 and qemu-riscv64 as the example. Outlined necessary CMake flags for cross-compiling with Clang, including CMAKE_C_COMPILER_TARGET, CMAKE_CXX_COMPILER_TARGET, and LLVM_ENABLE_LLD=ON. Switched from CMAKE_SYSROOT to LIBC_KERNEL_HEADERS and added the gcc-riscv64-linux-gnu package dependency to ensure sysroot issues on Debian-based systems are avoided while retaining access to cross-compiler runtime objects.

Explained the self-hosted libc-hermetic-tests target as the required target for executing tests during a standalone cross build, since the standard check-libc tests are not hermetic.

Refactored existing CMake examples in full_cross_build.rst to use -S and -B flags instead of cd and mkdir.

Removed prompt characters from code blocks and separated host environment setup into explicit code blocks for easier copy-pasting. Also removed the initial 'cd llvm-project' directory changes to reduce boilerplate.

Added a cross-reference to the new emulator section in build_and_test.rst.

---
Full diff: https://github.com/llvm/llvm-project/pull/188838.diff


2 Files Affected:

- (modified) libc/docs/build_and_test.rst (+7) 
- (modified) libc/docs/full_cross_build.rst (+103-16) 


``````````diff
diff --git a/libc/docs/build_and_test.rst b/libc/docs/build_and_test.rst
index d608591288cf1..ddbbe1a8897fb 100644
--- a/libc/docs/build_and_test.rst
+++ b/libc/docs/build_and_test.rst
@@ -108,3 +108,10 @@ As an example, to build and test in a container for 32-bit Arm:
         --arch arm docker.io/ubuntu:jammy bash
 
 #. Install necessary packages, invoke CMake, build, and run tests.
+
+Building and Testing with an Emulator
+=====================================
+
+If you are cross-compiling the libc for a different architecture, you can use an emulator
+such as QEMU to run the tests directly on your host without a container. See
+:ref:`full_cross_build` for detailed instructions on configuring CMake to use an emulator.
diff --git a/libc/docs/full_cross_build.rst b/libc/docs/full_cross_build.rst
index 436396d7acf46..e452910fc5780 100644
--- a/libc/docs/full_cross_build.rst
+++ b/libc/docs/full_cross_build.rst
@@ -43,25 +43,43 @@ to explicitly build the build tools first and then build the libc. A point to
 keep in mind is that the compiler used should be capable of building for the
 host as well as the target.
 
+.. note::
+   Even though the LLVM libc provides its own complete C library implementation,
+   compiling it for a Linux target still requires the Linux kernel API headers for
+   that architecture. On Debian-based systems, these and other standard cross-compilation 
+   runtimes (like ``libgcc``) can be installed via packages like 
+   ``gcc-riscv64-linux-gnu`` and ``linux-libc-dev-riscv64-cross`` (or similar for 
+   other architectures). You will need to point CMake to the kernel headers using 
+   ``-DLIBC_KERNEL_HEADERS`` (e.g., 
+   ``-DLIBC_KERNEL_HEADERS=/usr/riscv64-linux-gnu/include``) so the libc build
+   can find headers like ``asm/unistd.h``.
+
 CMake configure step
 --------------------
 
+First, set up the environment variables for your compiler and target:
+
+.. code-block:: sh
+
+  C_COMPILER=clang
+  CXX_COMPILER=clang++
+  TARGET_TRIPLE=aarch64-linux-gnu
+
 Below is the CMake command to configure the standalone crossbuild of the libc.
 
 .. code-block:: sh
 
-  $> cd llvm-project  # The llvm-project checkout
-  $> mkdir build
-  $> cd build
-  $> C_COMPILER=<C compiler> # For example "clang"
-  $> CXX_COMPILER=<C++ compiler> # For example "clang++"
-  $> cmake ../runtimes  \
+  cmake \
+     -B build \
+     -S runtimes \
      -G Ninja \
      -DLLVM_ENABLE_RUNTIMES=libc  \
      -DCMAKE_C_COMPILER=$C_COMPILER \
      -DCMAKE_CXX_COMPILER=$CXX_COMPILER \
+     -DCMAKE_C_COMPILER_TARGET=$TARGET_TRIPLE \
+     -DCMAKE_CXX_COMPILER_TARGET=$TARGET_TRIPLE \
      -DLLVM_LIBC_FULL_BUILD=ON \
-     -DLIBC_TARGET_TRIPLE=<Your target triple> \
+     -DLIBC_TARGET_TRIPLE=$TARGET_TRIPLE \
      -DCMAKE_BUILD_TYPE=<Release|Debug>
 
 We will go over the special options passed to the ``cmake`` command above.
@@ -82,7 +100,7 @@ the libc for the target with the following command:
 
 .. code-block:: sh
 
-   $> ninja libc libm
+   ninja -C build libc libm
 
 The above ``ninja`` command will build the libc static archives ``libc.a`` and
 ``libm.a`` for the target specified with ``-DLIBC_TARGET_TRIPLE`` in the CMake
@@ -97,15 +115,21 @@ the libc for the target.
 CMake configure step
 --------------------
 
+First, set up the environment variables for your compiler and target:
+
 .. code-block:: sh
 
-  $> cd llvm-project  # The llvm-project checkout
-  $> mkdir build
-  $> cd build
-  $> C_COMPILER=<C compiler> # For example "clang"
-  $> CXX_COMPILER=<C++ compiler> # For example "clang++"
-  $> TARGET_TRIPLE=<Your target triple>
-  $> cmake ../llvm \
+  C_COMPILER=clang
+  CXX_COMPILER=clang++
+  TARGET_TRIPLE=aarch64-linux-gnu
+
+Then, configure the CMake build for the bootstrap build:
+
+.. code-block:: sh
+
+  cmake \
+     -B build \
+     -S llvm \
      -G Ninja \
      -DCMAKE_C_COMPILER=$C_COMPILER \
      -DCMAKE_CXX_COMPILER=$CXX_COMPILER \
@@ -129,7 +153,7 @@ The build step is similar to the other recipe:
 
 .. code-block:: sh
 
-  $> ninja libc
+  ninja -C build libc
 
 The above ninja command should build the libc static archives for the target
 specified with ``-DLLVM_RUNTIME_TARGETS``.
@@ -152,3 +176,66 @@ target triple as one of the supported GPU targets. Currently, this is either
 ``nvptx64-nvidia-cuda`` for NVIDIA GPUs or ``amdgcn-amd-amdhsa`` for AMD GPUs.
 More detailed information is provided in the :ref:`GPU
 documentation<libc_gpu_building>`.
+
+Building and Testing with an Emulator
+=====================================
+
+If you are cross-compiling the libc for a different architecture, you can use an emulator
+such as QEMU to run the tests. For instance, to cross-compile for ``riscv64`` and run tests
+using ``qemu-riscv64``, you can use the standalone cross build recipe with a few additional CMake flags.
+
+CMake configure step
+--------------------
+
+Assuming your system compiler (e.g., ``clang++``) supports the RISC-V target,
+you can configure the build as follows:
+
+.. code-block:: sh
+
+  cmake \
+     -B build \
+     -S runtimes \
+     -G Ninja \
+     -DLLVM_ENABLE_RUNTIMES=libc  \
+     -DCMAKE_C_COMPILER=clang \
+     -DCMAKE_CXX_COMPILER=clang++ \
+     -DCMAKE_C_COMPILER_TARGET=riscv64-linux-gnu \
+     -DCMAKE_CXX_COMPILER_TARGET=riscv64-linux-gnu \
+     -DLLVM_LIBC_FULL_BUILD=ON \
+     -DLIBC_TARGET_TRIPLE=riscv64-linux-gnu \
+     -DLIBC_KERNEL_HEADERS=/usr/riscv64-linux-gnu/include \
+     -DCMAKE_CROSSCOMPILING_EMULATOR=qemu-riscv64 \
+     -DLLVM_ENABLE_LLD=ON \
+     -DCMAKE_BUILD_TYPE=Debug
+
+The notable additions are:
+
+* **The compiler target** - We set ``-DCMAKE_C_COMPILER_TARGET=riscv64-linux-gnu`` and ``-DCMAKE_CXX_COMPILER_TARGET=riscv64-linux-gnu`` to tell CMake to pass the correct ``--target`` flags to ``clang`` so that it cross-compiles rather than building for the host.
+* **The target triple** - We set ``-DLIBC_TARGET_TRIPLE=riscv64-linux-gnu``
+* **The kernel headers** - We set ``-DLIBC_KERNEL_HEADERS=/usr/riscv64-linux-gnu/include``
+  to point to the target's Linux API headers (e.g. for ``asm/unistd.h``).
+* **The cross-compiling emulator** - We set ``-DCMAKE_CROSSCOMPILING_EMULATOR=qemu-riscv64``
+  to tell CMake how to execute the compiled unittests. Note that this requires that
+  ``qemu-riscv64`` is installed and available in your ``$PATH``.
+* **LLD Linker** - We set ``-DLLVM_ENABLE_LLD=ON`` to ensure the test suite is linked using ``lld``, which is necessary for cross-compilation.
+
+Build and Test step
+-------------------
+
+You can then build the libc using:
+
+.. code-block:: sh
+
+  ninja -C build libc
+
+To run the tests for the cross-compiled libc, you must use the hermetic test
+suite, which is entirely self-hosted.
+
+.. code-block:: sh
+
+  ninja -C build libc-hermetic-tests
+
+.. note::
+   The standard ``check-libc`` target relies on the target's system C++ and C library
+   headers. Because these tests aren't hermetic, they are not expected to work for
+   a standalone cross-compilation build.

``````````

</details>


https://github.com/llvm/llvm-project/pull/188838


More information about the libc-commits mailing list