Skip to content

Commit 97ccd14

Browse files
committed
[llvm][docs] Update CMake commands for cross compiling Arm builtins
This does a few things: * LLVM_CONFIG_PATH is deprecated, use LLVM_CMAKE_DIR instead. * Don't use $ before command examples. I would normally, but the key cmake commands didn't use it so I removed it from all commands. * Makes the commands shown full commands, so you don't have to piece them together. * Uses shell variables to cut down on repetition and make this easier to port to other targets. * Adds a few options to disable more compiler-rt things. * Include test options in the first cmake command, so you don't have to re-do the whole thing after you read the testing section. * Removes the section about using BaremetalARM.cmake. The closest I got to getting that cache to work was: ``` SYSROOT=/home/david.spickett/arm-gnu-toolchain-14.3.rel1-x86_64-arm-none-eabi/arm-none-eabi/libc LLVM_TOOLCHAIN=/home/david.spickett/LLVM-20.1.8-Linux-X64/ cmake \ -G Ninja \ -DCMAKE_C_COMPILER=${LLVM_TOOLCHAIN}/bin/clang \ -DBAREMETAL_ARMV6M_SYSROOT=${SYSROOT} \ -DBAREMETAL_ARMV7M_SYSROOT=${SYSROOT} \ -DBAREMETAL_ARMV7EM_SYSROOT=${SYSROOT} \ -DCMAKE_BUILD_TYPE=Release \ -DLLVM_ENABLE_RUNTIMES="compiler-rt" \ -C ../llvm-project/clang/cmake/caches/BaremetalARM.cmake \ -DCOMPILER_RT_BUILD_BUILTINS=ON \ -DCOMPILER_RT_BUILD_LIBFUZZER=OFF \ -DCOMPILER_RT_BUILD_MEMPROF=OFF \ -DCOMPILER_RT_BUILD_PROFILE=OFF \ -DCOMPILER_RT_BUILD_CTX_PROFILE=OFF \ -DCOMPILER_RT_BUILD_SANITIZERS=OFF \ -DCOMPILER_RT_BUILD_XRAY=OFF \ -DCOMPILER_RT_BUILD_ORC=OFF \ -DCOMPILER_RT_BUILD_CRT=OFF \ ../llvm-project/runtimes ``` All this does is build the x86 builtins. I tried forcing the issue with: ``` -DBUILTIN_SUPPORTED_ARCH="armv7m;armv6m;armv7em" \ ``` But again, just x86. It's probably something deep in compiler-rt failing a compiler check for the Arm targets. Even if that's the case, fixing that means adding more options to the cmake command. I can't find evidence of a full command using this cache file since the commit that introduced it and that command no longer works. I think if you ever got this to work again the command would be as long and complex as the ones already shown in the document. I would also argue that some of the other caches, for example Fuschia's, are much better example of multi-target runtimes builds. If what's in this document isn't enough, folks should be learning from those files and about the runtimes build overall before attempting anything complex (though it does not take much to be "complex").
1 parent f4972a2 commit 97ccd14

File tree

1 file changed

+124
-99
lines changed

1 file changed

+124
-99
lines changed

llvm/docs/HowToCrossCompileBuiltinsOnArm.rst

Lines changed: 124 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ using as many of the LLVM tools as we can, but it is possible to use GNU
2525
equivalents.
2626

2727
You will need:
28-
* A build of LLVM for the llvm-tools and ``llvm-config``.
28+
* A build of LLVM for the llvm-tools and LLVM CMake files.
2929
* A clang executable with support for the ``ARM`` target.
30-
* compiler-rt sources.
30+
* ``compiler-rt`` sources.
3131
* The ``qemu-arm`` user mode emulator.
3232
* An ``arm-linux-gnueabihf`` sysroot.
3333

@@ -52,78 +52,94 @@ toolchain from https://developer.arm.com/open-source/gnu-toolchain/gnu-a/downloa
5252
Building compiler-rt builtins for Arm
5353
=====================================
5454

55-
We will be doing a standalone build of compiler-rt using the following cmake
56-
options::
55+
We will be doing a standalone build of compiler-rt. The command is shown below.
56+
Shell variables are used to simplify some of the options::
5757

58-
cmake path/to/compiler-rt \
58+
LLVM_TOOLCHAIN=<path-to-llvm-install>/
59+
TARGET_TRIPLE=arm-none-linux-gnueabihf
60+
GCC_TOOLCHAIN=<path-to-gcc-toolchain>
61+
SYSROOT=${GCC_TOOLCHAIN}/${TARGET_TRIPLE}/libc
62+
COMPILE_FLAGS="-march=armv7-a"
63+
64+
cmake ../llvm-project/compiler-rt \
5965
-G Ninja \
60-
-DCMAKE_AR=/path/to/llvm-ar \
61-
-DCMAKE_ASM_COMPILER_TARGET="arm-linux-gnueabihf" \
62-
-DCMAKE_ASM_FLAGS="build-c-flags" \
63-
-DCMAKE_C_COMPILER=/path/to/clang \
64-
-DCMAKE_C_COMPILER_TARGET="arm-linux-gnueabihf" \
65-
-DCMAKE_C_FLAGS="build-c-flags" \
66+
-DCMAKE_AR=${LLVM_TOOLCHAIN}/bin/llvm-ar \
67+
-DCMAKE_NM=${LLVM_TOOLCHAIN}/bin/llvm-nm \
68+
-DCMAKE_RANLIB=${LLVM_TOOLCHAIN}/bin/llvm-ranlib \
69+
-DLLVM_CMAKE_DIR="${LLVM_TOOLCHAIN}/lib/cmake/llvm" \
70+
-DCMAKE_SYSROOT="${SYSROOT}" \
71+
-DCMAKE_ASM_COMPILER_TARGET="${TARGET_TRIPLE}" \
72+
-DCMAKE_ASM_FLAGS="${COMPILE_FLAGS}" \
73+
-DCMAKE_C_COMPILER_TARGET="${TARGET_TRIPLE}" \
74+
-DCMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN=${GCC_TOOLCHAIN} \
75+
-DCMAKE_C_COMPILER=${LLVM_TOOLCHAIN}/bin/clang \
76+
-DCMAKE_C_FLAGS="${COMPILE_FLAGS}" \
77+
-DCMAKE_CXX_COMPILER_TARGET="${TARGET_TRIPLE}" \
78+
-DCMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN=${GCC_TOOLCHAIN} \
79+
-DCMAKE_CXX_COMPILER=${LLVM_TOOLCHAIN}/bin/clang \
80+
-DCMAKE_CXX_FLAGS="${COMPILE_FLAGS}" \
6681
-DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=lld" \
67-
-DCMAKE_NM=/path/to/llvm-nm \
68-
-DCMAKE_RANLIB=/path/to/llvm-ranlib \
6982
-DCOMPILER_RT_BUILD_BUILTINS=ON \
7083
-DCOMPILER_RT_BUILD_LIBFUZZER=OFF \
7184
-DCOMPILER_RT_BUILD_MEMPROF=OFF \
7285
-DCOMPILER_RT_BUILD_PROFILE=OFF \
86+
-DCOMPILER_RT_BUILD_CTX_PROFILE=OFF \
7387
-DCOMPILER_RT_BUILD_SANITIZERS=OFF \
7488
-DCOMPILER_RT_BUILD_XRAY=OFF \
89+
-DCOMPILER_RT_BUILD_ORC=OFF \
90+
-DCOMPILER_RT_BUILD_CRT=OFF \
7591
-DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON \
76-
-DLLVM_CONFIG_PATH=/path/to/llvm-config
92+
-DCOMPILER_RT_EMULATOR="qemu-arm -L ${SYSROOT}" \
93+
-DCOMPILER_RT_INCLUDE_TESTS=ON \
94+
-DCOMPILER_RT_TEST_COMPILER=${LLVM_TOOLCHAIN}/bin/clang \
95+
-DCOMPILER_RT_TEST_COMPILER_CFLAGS="--target=${TARGET_TRIPLE} ${COMPILE_FLAGS} --gcc-toolchain=${GCC_TOOLCHAIN} --sysroot=${SYSROOT} -fuse-ld=lld"
7796

78-
The ``build-c-flags`` need to be sufficient to pass the C-make compiler check,
79-
compile compiler-rt, and if you are running the tests, compile and link the
80-
tests. When cross-compiling with clang we will need to pass sufficient
81-
information to generate code for the Arm architecture we are targeting.
97+
.. note::
98+
The command above also enables tests. Enabling tests is not required, more details
99+
in the testing section.
82100

83-
We will need to select:
84-
* The Arm target and Armv7-A architecture with ``--target=arm-linux-gnueabihf -march=armv7a``.
85-
* Whether to generate Arm (the default) or Thumb instructions (``-mthumb``).
101+
``CMAKE_<LANGUAGE>_<OPTION>`` options are set so that the correct ``--target``,
102+
``--sysroot``, ``--gcc-toolchain`` and ``-march`` options will be given to the
103+
compilers.
86104

87-
When using a GCC ``arm-linux-gnueabihf`` toolchain the following flags are
88-
needed to pick up the includes and libraries:
105+
The combination of these settings needs to be enough to pass CMake's compiler
106+
checks, compile compiler-rt and build the test cases.
89107

90-
* ``--gcc-toolchain=/path/to/dir/toolchain``
91-
* ``--sysroot=/path/to/toolchain/arm-linux-gnueabihf/libc``
108+
The flags need to select:
109+
* The Arm target (``--target arm-none-linux-gnueabihf``)
110+
* The Arm architecture level (``-march=armv7-a``)
111+
* Whether to generate Arm (``-marm``, the default) or Thumb (``-mthumb``) instructions.
92112

93-
In this example we will be adding all of the command line options to both
94-
``CMAKE_C_FLAGS`` and ``CMAKE_ASM_FLAGS``. There are cmake flags to pass some of
95-
these options individually which can be used to simplify the ``build-c-flags``::
113+
It is possible to pass all these flags to CMake using ``CMAKE_<LANGUAGE>_FLAGS``,
114+
but the command above uses standard CMake options instead. If you need to
115+
add flags that CMake cannot generate automatically, add them to
116+
``CMAKE_<LANGUAGE>_FLAGS``.
96117

97-
-DCMAKE_C_COMPILER_TARGET="arm-linux-gnueabihf"
98-
-DCMAKE_ASM_COMPILER_TARGET="arm-linux-gnueabihf"
99-
-DCMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN=/path/to/dir/toolchain
100-
-DCMAKE_SYSROOT=/path/to/dir/toolchain/arm-linux-gnueabihf/libc
118+
When CMake has finished, build with Ninja::
101119

102-
Once cmake has completed the builtins can be built with ``ninja builtins``
120+
ninja builtins
103121

104122
Testing compiler-rt builtins using qemu-arm
105123
===========================================
106124

107-
To test the builtins library we need to add a few more cmake flags to enable
108-
testing and set up the compiler and flags for test case. We must also tell
109-
cmake that we wish to run the tests on ``qemu-arm``::
125+
The following options are required to enable tests::
126+
127+
-DCOMPILER_RT_EMULATOR="qemu-arm -L ${SYSROOT}" \
128+
-DCOMPILER_RT_INCLUDE_TESTS=ON \
129+
-DCOMPILER_RT_TEST_COMPILER=${LLVM_TOOLCHAIN}/bin/clang \
130+
-DCOMPILER_RT_TEST_COMPILER_CFLAGS="--target=${TARGET_TRIPLE} -march=armv7-a --gcc-toolchain=${GCC_TOOLCHAIN} --sysroot=${SYSROOT} -fuse-ld=lld"
110131

111-
-DCOMPILER_RT_EMULATOR="qemu-arm -L /path/to/armhf/sysroot"
112-
-DCOMPILER_RT_INCLUDE_TESTS=ON
113-
-DCOMPILER_RT_TEST_COMPILER="/path/to/clang"
114-
-DCOMPILER_RT_TEST_COMPILER_CFLAGS="test-c-flags"
132+
This tells compiler-rt that we want to run tests on ``qemu-arm``. If you do not
133+
want to run tests, remove these options from the CMake command.
115134

116-
The ``/path/to/armhf/sysroot`` should be the same as the one passed to
117-
``--sysroot`` in the ``build-c-flags``.
135+
Note that ``COMPILER_RT_TEST_COMPILER_CFLAGS`` contains the equivalent of the
136+
options CMake generated for us with the first command. We must pass them
137+
manually here because standard options like ``CMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN``
138+
do not apply here.
118139

119-
The ``test-c-flags`` need to include the target, architecture, gcc-toolchain,
120-
sysroot and Arm/Thumb state. The additional cmake defines such as
121-
``CMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN`` do not apply when building the tests. If
122-
you have put all of these in ``build-c-flags`` then these can be repeated. If you
123-
wish to use lld to link the tests then add ``-fuse-ld=lld``.
140+
When CMake has finished, run the tests::
124141

125-
Once cmake has completed the tests can be built and run using
126-
``ninja check-builtins``
142+
ninja check-builtins
127143

128144
Troubleshooting
129145
===============
@@ -133,9 +149,10 @@ The cmake try compile stage fails
133149
At an early stage cmake will attempt to compile and link a simple C program to
134150
test if the toolchain is working.
135151

136-
This stage can often fail at link time if the ``--sysroot=`` and
152+
This stage can often fail at link time if the ``--sysroot=``, ``--target`` or
137153
``--gcc-toolchain=`` options are not passed to the compiler. Check the
138-
``CMAKE_C_FLAGS`` and ``CMAKE_C_COMPILER_TARGET`` flags.
154+
``CMAKE_<LANGUAGE>_FLAGS`` and ``CMAKE_<LANGAUGE>_COMPILER_TARGET`` flags along
155+
with any of the specific CMake sysroot and toolchain options.
139156

140157
It can be useful to build a simple example outside of cmake with your toolchain
141158
to make sure it is working. For example::
@@ -179,10 +196,10 @@ The flags used to build the tests are not the same as those used to build the
179196
builtins. The c flags are provided by ``COMPILER_RT_TEST_COMPILE_CFLAGS`` and
180197
the ``CMAKE_C_COMPILER_TARGET``, ``CMAKE_ASM_COMPILER_TARGET``,
181198
``CMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN`` and ``CMAKE_SYSROOT`` flags are not
182-
applied.
199+
applied to tests.
183200

184201
Make sure that ``COMPILER_RT_TEST_COMPILE_CFLAGS`` contains all the necessary
185-
information.
202+
flags.
186203

187204

188205
Modifications for other Targets
@@ -206,13 +223,13 @@ You will need to use an ``arm-linux-gnueabi`` GNU toolchain for soft-float.
206223
AArch64 Target
207224
--------------
208225
The instructions for Arm can be used for AArch64 by substituting AArch64
209-
equivalents for the sysroot, emulator and target.
226+
equivalents for the sysroot, emulator and target::
210227

211-
* ``-DCMAKE_C_COMPILER_TARGET=aarch64-linux-gnu``
212-
* ``-DCOMPILER_RT_EMULATOR="qemu-aarch64 -L /path/to/aarch64/sysroot``
228+
-DCMAKE_C_COMPILER_TARGET=aarch64-linux-gnu
229+
-DCOMPILER_RT_EMULATOR="qemu-aarch64 -L /path/to/aarch64/sysroot
213230

214-
The CMAKE_C_FLAGS and COMPILER_RT_TEST_COMPILER_CFLAGS may also need:
215-
``"--sysroot=/path/to/aarch64/sysroot --gcc-toolchain=/path/to/gcc-toolchain"``
231+
You will also have to update any use of the target triple in compiler flags.
232+
For instance in ``CMAKE_C_FLAGS`` and ``COMPILER_RT_TEST_COMPILER_CFLAGS``.
216233

217234
Armv6-m, Armv7-m and Armv7E-M targets
218235
-------------------------------------
@@ -235,31 +252,55 @@ into a binary and execute the tests correctly but it will not catch if the
235252
builtins use instructions that are supported on Armv7-A but not Armv6-M,
236253
Armv7-M and Armv7E-M.
237254

238-
To get the cmake compile test to pass you will need to pass the libraries
239-
needed to successfully link the cmake test via ``CMAKE_CFLAGS``::
240-
241-
-DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY \
242-
-DCOMPILER_RT_OS_DIR="baremetal" \
243-
-DCOMPILER_RT_BUILD_BUILTINS=ON \
244-
-DCOMPILER_RT_BUILD_SANITIZERS=OFF \
245-
-DCOMPILER_RT_BUILD_XRAY=OFF \
246-
-DCOMPILER_RT_BUILD_LIBFUZZER=OFF \
247-
-DCOMPILER_RT_BUILD_PROFILE=OFF \
248-
-DCMAKE_C_COMPILER=${host_install_dir}/bin/clang \
249-
-DCMAKE_C_COMPILER_TARGET="your *-none-eabi target" \
250-
-DCMAKE_ASM_COMPILER_TARGET="your *-none-eabi target" \
251-
-DCMAKE_AR=/path/to/llvm-ar \
252-
-DCMAKE_NM=/path/to/llvm-nm \
253-
-DCMAKE_RANLIB=/path/to/llvm-ranlib \
254-
-DCOMPILER_RT_BAREMETAL_BUILD=ON \
255-
-DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON \
256-
-DLLVM_CONFIG_PATH=/path/to/llvm-config \
257-
-DCMAKE_C_FLAGS="build-c-flags" \
258-
-DCMAKE_ASM_FLAGS="build-c-flags" \
259-
-DCOMPILER_RT_EMULATOR="qemu-arm -L /path/to/armv7-A/sysroot" \
260-
-DCOMPILER_RT_INCLUDE_TESTS=ON \
261-
-DCOMPILER_RT_TEST_COMPILER="/path/to/clang" \
262-
-DCOMPILER_RT_TEST_COMPILER_CFLAGS="test-c-flags"
255+
Below is an example that builds the builtins for Armv7-M, but runs the tests
256+
as Armv7-A. It is presented in full, but is very similar to the earlier
257+
command for Armv7-A build and test::
258+
259+
LLVM_TOOLCHAIN=<path-to-llvm-install>/
260+
TARGET_TRIPLE=arm-none-eabi
261+
GCC_TOOLCHAIN=<path-to-gcc-toolchain>
262+
SYSROOT=${GCC_TOOLCHAIN}/${TARGET_TRIPLE}/libc
263+
COMPILE_FLAGS="-march=armv7-m -mfpu=vfpv2"
264+
265+
cmake ../llvm-project/compiler-rt \
266+
-G Ninja \
267+
-DCMAKE_AR=${LLVM_TOOLCHAIN}/bin/llvm-ar \
268+
-DCMAKE_NM=${LLVM_TOOLCHAIN}/bin/llvm-nm \
269+
-DCMAKE_RANLIB=${LLVM_TOOLCHAIN}/bin/llvm-ranlib \
270+
-DLLVM_CMAKE_DIR="${LLVM_TOOLCHAIN}/lib/cmake/llvm" \
271+
-DCMAKE_SYSROOT="${SYSROOT}" \
272+
-DCMAKE_ASM_COMPILER_TARGET="${TARGET_TRIPLE}" \
273+
-DCMAKE_ASM_FLAGS="${COMPILE_FLAGS}" \
274+
-DCMAKE_C_COMPILER_TARGET="${TARGET_TRIPLE}" \
275+
-DCMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN=${GCC_TOOLCHAIN} \
276+
-DCMAKE_C_COMPILER=${LLVM_TOOLCHAIN}/bin/clang \
277+
-DCMAKE_C_FLAGS="${COMPILE_FLAGS}" \
278+
-DCMAKE_CXX_COMPILER_TARGET="${TARGET_TRIPLE}" \
279+
-DCMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN=${GCC_TOOLCHAIN} \
280+
-DCMAKE_CXX_COMPILER=${LLVM_TOOLCHAIN}/bin/clang \
281+
-DCMAKE_CXX_FLAGS="${COMPILE_FLAGS}" \
282+
-DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=lld" \
283+
-DCOMPILER_RT_BUILD_BUILTINS=ON \
284+
-DCOMPILER_RT_BUILD_LIBFUZZER=OFF \
285+
-DCOMPILER_RT_BUILD_MEMPROF=OFF \
286+
-DCOMPILER_RT_BUILD_PROFILE=OFF \
287+
-DCOMPILER_RT_BUILD_CTX_PROFILE=OFF \
288+
-DCOMPILER_RT_BUILD_SANITIZERS=OFF \
289+
-DCOMPILER_RT_BUILD_XRAY=OFF \
290+
-DCOMPILER_RT_BUILD_ORC=OFF \
291+
-DCOMPILER_RT_BUILD_CRT=OFF \
292+
-DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON \
293+
-DCOMPILER_RT_EMULATOR="qemu-arm -L <path to arm-none-linux-gnueabihf toolchain>/arm-none-linux-gnueabihf/libc" \
294+
-DCOMPILER_RT_INCLUDE_TESTS=ON \
295+
-DCOMPILER_RT_TEST_COMPILER=${LLVM_TOOLCHAIN}/bin/clang \
296+
-DCOMPILER_RT_TEST_COMPILER_CFLAGS="--target=arm-none-linux-gnueabihf -march=armv7-a --gcc-toolchain=<path to arm-none-linux-gnueabihf toolchain> --sysroot=<path to arm-none-linux-gnueabihf toolchain>/arm-none-linux-gnueabihf/libc -fuse-ld=lld" \
297+
-DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY \
298+
-DCOMPILER_RT_OS_DIR="baremetal" \
299+
-DCOMPILER_RT_BAREMETAL_BUILD=ON
300+
301+
.. note::
302+
The sysroot used for compiling the tests is ``arm-linux-gnueabihf``, not
303+
``arm-none-eabi`` which is used when compiling the builtins.
263304

264305
The Armv6-M builtins will use the soft-float ABI. When compiling the tests for
265306
Armv7-A we must include ``"-mthumb -mfloat-abi=soft -mfpu=none"`` in the
@@ -270,19 +311,3 @@ mismatches between the M-profile objects from compiler-rt and the A-profile
270311
objects from the test. The lld linker does not check the profile
271312
BuildAttribute so it can be used to link the tests by adding ``-fuse-ld=lld`` to the
272313
``COMPILER_RT_TEST_COMPILER_CFLAGS``.
273-
274-
Alternative using a cmake cache
275-
-------------------------------
276-
If you wish to build, but not test compiler-rt for Armv6-M, Armv7-M or Armv7E-M
277-
the easiest way is to use the ``BaremetalARM.cmake`` recipe in ``clang/cmake/caches``.
278-
279-
You will need a bare metal sysroot such as that provided by the GNU ARM Embedded
280-
toolchain.
281-
282-
The libraries can be built with the cmake options::
283-
284-
-DBAREMETAL_ARMV6M_SYSROOT=/path/to/bare/metal/toolchain/arm-none-eabi \
285-
-DBAREMETAL_ARMV7M_SYSROOT=/path/to/bare/metal/toolchain/arm-none-eabi \
286-
-DBAREMETAL_ARMV7EM_SYSROOT=/path/to/bare/metal/toolchain/arm-none-eabi \
287-
-C /path/to/llvm/source/tools/clang/cmake/caches/BaremetalARM.cmake \
288-
/path/to/llvm

0 commit comments

Comments
 (0)