@@ -25,12 +25,16 @@ using as many of the LLVM tools as we can, but it is possible to use GNU
25
25
equivalents.
26
26
27
27
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 .
29
29
* A clang executable with support for the ``ARM `` target.
30
- * compiler-rt sources.
30
+ * `` compiler-rt `` sources.
31
31
* The ``qemu-arm `` user mode emulator.
32
32
* An ``arm-linux-gnueabihf `` sysroot.
33
33
34
+ .. note ::
35
+ An existing sysroot is required because some of the builtins include C library
36
+ headers and a sysroot is the easiest way to get those.
37
+
34
38
In this example we will be using ``ninja `` as the build tool.
35
39
36
40
See https://compiler-rt.llvm.org/ for information about the dependencies
@@ -52,78 +56,94 @@ toolchain from https://developer.arm.com/open-source/gnu-toolchain/gnu-a/downloa
52
56
Building compiler-rt builtins for Arm
53
57
=====================================
54
58
55
- We will be doing a standalone build of compiler-rt using the following cmake
56
- options::
59
+ We will be doing a standalone build of compiler-rt. The command is shown below.
60
+ Shell variables are used to simplify some of the options::
61
+
62
+ LLVM_TOOLCHAIN=<path-to-llvm-install>/
63
+ TARGET_TRIPLE=arm-none-linux-gnueabihf
64
+ GCC_TOOLCHAIN=<path-to-gcc-toolchain>
65
+ SYSROOT=${GCC_TOOLCHAIN}/${TARGET_TRIPLE}/libc
66
+ COMPILE_FLAGS="-march=armv7-a"
57
67
58
- cmake path/to /compiler-rt \
68
+ cmake ../llvm-project /compiler-rt \
59
69
-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" \
70
+ -DCMAKE_AR=${LLVM_TOOLCHAIN}/bin/llvm-ar \
71
+ -DCMAKE_NM=${LLVM_TOOLCHAIN}/bin/llvm-nm \
72
+ -DCMAKE_RANLIB=${LLVM_TOOLCHAIN}/bin/llvm-ranlib \
73
+ -DLLVM_CMAKE_DIR="${LLVM_TOOLCHAIN}/lib/cmake/llvm" \
74
+ -DCMAKE_SYSROOT="${SYSROOT}" \
75
+ -DCMAKE_ASM_COMPILER_TARGET="${TARGET_TRIPLE}" \
76
+ -DCMAKE_ASM_FLAGS="${COMPILE_FLAGS}" \
77
+ -DCMAKE_C_COMPILER_TARGET="${TARGET_TRIPLE}" \
78
+ -DCMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN=${GCC_TOOLCHAIN} \
79
+ -DCMAKE_C_COMPILER=${LLVM_TOOLCHAIN}/bin/clang \
80
+ -DCMAKE_C_FLAGS="${COMPILE_FLAGS}" \
81
+ -DCMAKE_CXX_COMPILER_TARGET="${TARGET_TRIPLE}" \
82
+ -DCMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN=${GCC_TOOLCHAIN} \
83
+ -DCMAKE_CXX_COMPILER=${LLVM_TOOLCHAIN}/bin/clang \
84
+ -DCMAKE_CXX_FLAGS="${COMPILE_FLAGS}" \
66
85
-DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=lld" \
67
- -DCMAKE_NM=/path/to/llvm-nm \
68
- -DCMAKE_RANLIB=/path/to/llvm-ranlib \
69
86
-DCOMPILER_RT_BUILD_BUILTINS=ON \
70
87
-DCOMPILER_RT_BUILD_LIBFUZZER=OFF \
71
88
-DCOMPILER_RT_BUILD_MEMPROF=OFF \
72
89
-DCOMPILER_RT_BUILD_PROFILE=OFF \
90
+ -DCOMPILER_RT_BUILD_CTX_PROFILE=OFF \
73
91
-DCOMPILER_RT_BUILD_SANITIZERS=OFF \
74
92
-DCOMPILER_RT_BUILD_XRAY=OFF \
93
+ -DCOMPILER_RT_BUILD_ORC=OFF \
94
+ -DCOMPILER_RT_BUILD_CRT=OFF \
75
95
-DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON \
76
- -DLLVM_CONFIG_PATH=/path/to/llvm-config
96
+ -DCOMPILER_RT_EMULATOR="qemu-arm -L ${SYSROOT}" \
97
+ -DCOMPILER_RT_INCLUDE_TESTS=ON \
98
+ -DCOMPILER_RT_TEST_COMPILER=${LLVM_TOOLCHAIN}/bin/clang \
99
+ -DCOMPILER_RT_TEST_COMPILER_CFLAGS="--target=${TARGET_TRIPLE} ${COMPILE_FLAGS} --gcc-toolchain=${GCC_TOOLCHAIN} --sysroot=${SYSROOT} -fuse-ld=lld"
77
100
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.
101
+ .. note ::
102
+ The command above also enables tests. Enabling tests is not required, more details
103
+ in the testing section.
82
104
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 ``) .
105
+ `` CMAKE_<LANGUAGE>_<OPTION> `` options are set so that the correct `` --target ``,
106
+ `` --sysroot ``, ``--gcc-toolchain `` and `` -march `` options will be given to the
107
+ compilers .
86
108
87
- When using a GCC `` arm-linux-gnueabihf `` toolchain the following flags are
88
- needed to pick up the includes and libraries:
109
+ The combination of these settings needs to be enough to pass CMake's compiler
110
+ checks, compile compiler-rt and build the test cases.
89
111
90
- * ``--gcc-toolchain=/path/to/dir/toolchain ``
91
- * ``--sysroot=/path/to/toolchain/arm-linux-gnueabihf/libc ``
112
+ The flags need to select:
113
+ * The Arm target (``--target arm-none-linux-gnueabihf ``)
114
+ * The Arm architecture level (``-march=armv7-a ``)
115
+ * Whether to generate Arm (``-marm ``, the default) or Thumb (``-mthumb ``) instructions.
92
116
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 ``::
117
+ It is possible to pass all these flags to CMake using ``CMAKE_<LANGUAGE>_FLAGS ``,
118
+ but the command above uses standard CMake options instead. If you need to
119
+ add flags that CMake cannot generate automatically, add them to
120
+ ``CMAKE_<LANGUAGE>_FLAGS ``.
96
121
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
122
+ When CMake has finished, build with Ninja::
101
123
102
- Once cmake has completed the builtins can be built with `` ninja builtins ``
124
+ ninja builtins
103
125
104
126
Testing compiler-rt builtins using qemu-arm
105
127
===========================================
106
128
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 ``::
129
+ The following options are required to enable tests::
130
+
131
+ -DCOMPILER_RT_EMULATOR="qemu-arm -L ${SYSROOT}" \
132
+ -DCOMPILER_RT_INCLUDE_TESTS=ON \
133
+ -DCOMPILER_RT_TEST_COMPILER=${LLVM_TOOLCHAIN}/bin/clang \
134
+ -DCOMPILER_RT_TEST_COMPILER_CFLAGS="--target=${TARGET_TRIPLE} -march=armv7-a --gcc-toolchain=${GCC_TOOLCHAIN} --sysroot=${SYSROOT} -fuse-ld=lld"
110
135
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"
136
+ This tells compiler-rt that we want to run tests on ``qemu-arm ``. If you do not
137
+ want to run tests, remove these options from the CMake command.
115
138
116
- The ``/path/to/armhf/sysroot `` should be the same as the one passed to
117
- ``--sysroot `` in the ``build-c-flags ``.
139
+ Note that ``COMPILER_RT_TEST_COMPILER_CFLAGS `` contains the equivalent of the
140
+ options CMake generated for us with the first command. We must pass them
141
+ manually here because standard options like ``CMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN ``
142
+ do not apply here.
118
143
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 ``.
144
+ When CMake has finished, run the tests::
124
145
125
- Once cmake has completed the tests can be built and run using
126
- ``ninja check-builtins ``
146
+ ninja check-builtins
127
147
128
148
Troubleshooting
129
149
===============
@@ -133,9 +153,10 @@ The cmake try compile stage fails
133
153
At an early stage cmake will attempt to compile and link a simple C program to
134
154
test if the toolchain is working.
135
155
136
- This stage can often fail at link time if the ``--sysroot= `` and
156
+ This stage can often fail at link time if the ``--sysroot= ``, `` --target `` or
137
157
``--gcc-toolchain= `` options are not passed to the compiler. Check the
138
- ``CMAKE_C_FLAGS `` and ``CMAKE_C_COMPILER_TARGET `` flags.
158
+ ``CMAKE_<LANGUAGE>_FLAGS `` and ``CMAKE_<LANGAUGE>_COMPILER_TARGET `` flags along
159
+ with any of the specific CMake sysroot and toolchain options.
139
160
140
161
It can be useful to build a simple example outside of cmake with your toolchain
141
162
to make sure it is working. For example::
@@ -179,10 +200,10 @@ The flags used to build the tests are not the same as those used to build the
179
200
builtins. The c flags are provided by ``COMPILER_RT_TEST_COMPILE_CFLAGS `` and
180
201
the ``CMAKE_C_COMPILER_TARGET ``, ``CMAKE_ASM_COMPILER_TARGET ``,
181
202
``CMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN `` and ``CMAKE_SYSROOT `` flags are not
182
- applied.
203
+ applied to tests .
183
204
184
205
Make sure that ``COMPILER_RT_TEST_COMPILE_CFLAGS `` contains all the necessary
185
- information .
206
+ flags .
186
207
187
208
188
209
Modifications for other Targets
@@ -206,13 +227,13 @@ You will need to use an ``arm-linux-gnueabi`` GNU toolchain for soft-float.
206
227
AArch64 Target
207
228
--------------
208
229
The instructions for Arm can be used for AArch64 by substituting AArch64
209
- equivalents for the sysroot, emulator and target.
230
+ equivalents for the sysroot, emulator and target::
210
231
211
- * `` -DCMAKE_C_COMPILER_TARGET=aarch64-linux-gnu ``
212
- * `` -DCOMPILER_RT_EMULATOR="qemu-aarch64 -L /path/to/aarch64/sysroot ``
232
+ -DCMAKE_C_COMPILER_TARGET=aarch64-linux-gnu
233
+ -DCOMPILER_RT_EMULATOR="qemu-aarch64 -L /path/to/aarch64/sysroot
213
234
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" ``
235
+ You will also have to update any use of the target triple in compiler flags.
236
+ For instance in `` CMAKE_C_FLAGS `` and `` COMPILER_RT_TEST_COMPILER_CFLAGS ``.
216
237
217
238
Armv6-m, Armv7-m and Armv7E-M targets
218
239
-------------------------------------
@@ -221,7 +242,7 @@ but more difficult. The main problems are:
221
242
222
243
* There is not a ``qemu-arm `` user-mode emulator for bare-metal systems.
223
244
``qemu-system-arm `` can be used but this is significantly more difficult
224
- to setup.
245
+ to setup. This document does not explain how to do this.
225
246
* The targets to compile compiler-rt have the suffix ``-none-eabi ``. This uses
226
247
the BareMetal driver in clang and by default will not find the libraries
227
248
needed to pass the cmake compiler check.
@@ -235,31 +256,68 @@ into a binary and execute the tests correctly but it will not catch if the
235
256
builtins use instructions that are supported on Armv7-A but not Armv6-M,
236
257
Armv7-M and Armv7E-M.
237
258
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"
259
+ This requires a second ``arm-none-eabi `` toolchain for building the builtins.
260
+ Using a bare-metal toolchain ensures that the target and C library details are
261
+ specific to bare-metal instead of using Linux settings. This means that some
262
+ tests may behave differently compared to real hardware, but at least the content
263
+ of the builtins library is correct.
264
+
265
+ Below is an example that builds the builtins for Armv7-M, but runs the tests
266
+ as Armv7-A. It is presented in full, but is very similar to the earlier
267
+ command for Armv7-A build and test::
268
+
269
+ LLVM_TOOLCHAIN=<path to llvm install>/
270
+
271
+ # For the builtins.
272
+ TARGET_TRIPLE=arm-none-eabi
273
+ GCC_TOOLCHAIN=<path to arm-none-eabi toolchain>/
274
+ SYSROOT=${GCC_TOOLCHAIN}/${TARGET_TRIPLE}/libc
275
+ COMPILE_FLAGS="-march=armv7-m -mfpu=vfpv2"
276
+
277
+ # For the test cases.
278
+ A_PROFILE_TARGET_TRIPLE=arm-none-linux-gnueabihf
279
+ A_PROFILE_GCC_TOOLCHAIN=<path to arm-none-linux-gnueabihf toolchain>/
280
+ A_PROFILE_SYSROOT=${A_PROFILE_GCC_TOOLCHAIN}/${A_PROFILE_TARGET_TRIPLE}/libc
281
+
282
+ cmake ../llvm-project/compiler-rt \
283
+ -G Ninja \
284
+ -DCMAKE_AR=${LLVM_TOOLCHAIN}/bin/llvm-ar \
285
+ -DCMAKE_NM=${LLVM_TOOLCHAIN}/bin/llvm-nm \
286
+ -DCMAKE_RANLIB=${LLVM_TOOLCHAIN}/bin/llvm-ranlib \
287
+ -DLLVM_CMAKE_DIR="${LLVM_TOOLCHAIN}/lib/cmake/llvm" \
288
+ -DCMAKE_SYSROOT="${SYSROOT}" \
289
+ -DCMAKE_ASM_COMPILER_TARGET="${TARGET_TRIPLE}" \
290
+ -DCMAKE_ASM_FLAGS="${COMPILE_FLAGS}" \
291
+ -DCMAKE_C_COMPILER_TARGET="${TARGET_TRIPLE}" \
292
+ -DCMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN=${GCC_TOOLCHAIN} \
293
+ -DCMAKE_C_COMPILER=${LLVM_TOOLCHAIN}/bin/clang \
294
+ -DCMAKE_C_FLAGS="${COMPILE_FLAGS}" \
295
+ -DCMAKE_CXX_COMPILER_TARGET="${TARGET_TRIPLE}" \
296
+ -DCMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN=${GCC_TOOLCHAIN} \
297
+ -DCMAKE_CXX_COMPILER=${LLVM_TOOLCHAIN}/bin/clang \
298
+ -DCMAKE_CXX_FLAGS="${COMPILE_FLAGS}" \
299
+ -DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=lld" \
300
+ -DCOMPILER_RT_BUILD_BUILTINS=ON \
301
+ -DCOMPILER_RT_BUILD_LIBFUZZER=OFF \
302
+ -DCOMPILER_RT_BUILD_MEMPROF=OFF \
303
+ -DCOMPILER_RT_BUILD_PROFILE=OFF \
304
+ -DCOMPILER_RT_BUILD_CTX_PROFILE=OFF \
305
+ -DCOMPILER_RT_BUILD_SANITIZERS=OFF \
306
+ -DCOMPILER_RT_BUILD_XRAY=OFF \
307
+ -DCOMPILER_RT_BUILD_ORC=OFF \
308
+ -DCOMPILER_RT_BUILD_CRT=OFF \
309
+ -DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON \
310
+ -DCOMPILER_RT_EMULATOR="qemu-arm -L ${A_PROFILE_SYSROOT}" \
311
+ -DCOMPILER_RT_INCLUDE_TESTS=ON \
312
+ -DCOMPILER_RT_TEST_COMPILER=${LLVM_TOOLCHAIN}/bin/clang \
313
+ -DCOMPILER_RT_TEST_COMPILER_CFLAGS="--target=${A_PROFILE_TARGET_TRIPLE} -march=armv7-a --gcc-toolchain=${A_PROFILE_GCC_TOOLCHAIN} --sysroot=${A_PROFILE_SYSROOT} -fuse-ld=lld" \
314
+ -DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY \
315
+ -DCOMPILER_RT_OS_DIR="baremetal" \
316
+ -DCOMPILER_RT_BAREMETAL_BUILD=ON
317
+
318
+ .. note ::
319
+ The sysroot used for compiling the tests is ``arm-linux-gnueabihf ``, not
320
+ ``arm-none-eabi `` which is used when compiling the builtins.
263
321
264
322
The Armv6-M builtins will use the soft-float ABI. When compiling the tests for
265
323
Armv7-A we must include ``"-mthumb -mfloat-abi=soft -mfpu=none" `` in the
@@ -270,19 +328,3 @@ mismatches between the M-profile objects from compiler-rt and the A-profile
270
328
objects from the test. The lld linker does not check the profile
271
329
BuildAttribute so it can be used to link the tests by adding ``-fuse-ld=lld `` to the
272
330
``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