blob: 6ad93c773b25758c428dcd25abc15d6892e66c5b [file] [log] [blame]
Peter Smith51bcf5f2017-11-07 09:40:05 +00001===================================================================
2How to Cross Compile Compiler-rt Builtins For Arm
3===================================================================
4
5Introduction
6============
7
8This document contains information about building and testing the builtins part
9of compiler-rt for an Arm target, from an x86_64 Linux machine.
10
11While this document concentrates on Arm and Linux the general principles should
12apply to other targets supported by compiler-rt. Further contributions for other
13targets are welcome.
14
15The instructions in this document depend on libraries and programs external to
16LLVM, there are many ways to install and configure these dependencies so you
17may need to adapt the instructions here to fit your own local situation.
18
19Prerequisites
20=============
21
Peter Smithf6775ea2018-12-18 12:40:19 +000022In this use case we'll be using cmake on a Debian-based Linux system,
Peter Smith51bcf5f2017-11-07 09:40:05 +000023cross-compiling from an x86_64 host to a hard-float Armv7-A target. We'll be
24using as many of the LLVM tools as we can, but it is possible to use GNU
25equivalents.
26
27 * ``A build of LLVM/clang for the llvm-tools and llvm-config``
Peter Smithf6775ea2018-12-18 12:40:19 +000028 * ``A clang executable with support for the ARM target``
29 * ``compiler-rt sources``
Peter Smith51bcf5f2017-11-07 09:40:05 +000030 * ``The qemu-arm user mode emulator``
31 * ``An arm-linux-gnueabihf sysroot``
32
Peter Smithf6775ea2018-12-18 12:40:19 +000033In this example we will be using ninja.
34
Peter Smith51bcf5f2017-11-07 09:40:05 +000035See https://compiler-rt.llvm.org/ for more information about the dependencies
36on clang and LLVM.
37
Peter Smithf6775ea2018-12-18 12:40:19 +000038See https://llvm.org/docs/GettingStarted.html for information about obtaining
39the source for LLVM and compiler-rt. Note that the getting started guide
40places compiler-rt in the projects subdirectory, but this is not essential and
41if you are using the BaremetalARM.cmake cache for v6-M, v7-M and v7-EM then
42compiler-rt must be placed in the runtimes directory.
43
Peter Smith51bcf5f2017-11-07 09:40:05 +000044``qemu-arm`` should be available as a package for your Linux distribution.
45
46The most complicated of the prequisites to satisfy is the arm-linux-gnueabihf
Peter Smithf6775ea2018-12-18 12:40:19 +000047sysroot. In theory it is possible to use the Linux distributions multiarch
48support to fulfill the dependencies for building but unfortunately due to
49/usr/local/include being added some host includes are selected. The easiest way
50to supply a sysroot is to download the arm-linux-gnueabihf toolchain. This can
51be found at:
52* https://developer.arm.com/open-source/gnu-toolchain/gnu-a/downloads for gcc 8 and above
53* https://releases.linaro.org/components/toolchain/binaries/ for gcc 4.9 to 7.3
Peter Smith51bcf5f2017-11-07 09:40:05 +000054
55Building compiler-rt builtins for Arm
56=====================================
57We will be doing a standalone build of compiler-rt using the following cmake
58options.
59
Peter Smithf6775ea2018-12-18 12:40:19 +000060* ``path/to/compiler-rt``
61* ``-G Ninja``
Peter Smith51bcf5f2017-11-07 09:40:05 +000062* ``-DCOMPILER_RT_BUILD_BUILTINS=ON``
63* ``-DCOMPILER_RT_BUILD_SANITIZERS=OFF``
64* ``-DCOMPILER_RT_BUILD_XRAY=OFF``
65* ``-DCOMPILER_RT_BUILD_LIBFUZZER=OFF``
66* ``-DCOMPILER_RT_BUILD_PROFILE=OFF``
67* ``-DCMAKE_C_COMPILER=/path/to/clang``
68* ``-DCMAKE_AR=/path/to/llvm-ar``
69* ``-DCMAKE_NM=/path/to/llvm-nm``
70* ``-DCMAKE_RANLIB=/path/to/llvm-ranlib``
71* ``-DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=lld"``
72* ``-DCMAKE_C_COMPILER_TARGET="arm-linux-gnueabihf"``
Peter Smithf6775ea2018-12-18 12:40:19 +000073* ``-DCMAKE_ASM_COMPILER_TARGET="arm-linux-gnueabihf"``
Peter Smith51bcf5f2017-11-07 09:40:05 +000074* ``-DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON``
75* ``-DLLVM_CONFIG_PATH=/path/to/llvm-config``
76* ``-DCMAKE_C_FLAGS="build-c-flags"``
Peter Smithf6775ea2018-12-18 12:40:19 +000077* ``-DCMAKE_ASM_FLAGS="build-c-flags"``
Peter Smith51bcf5f2017-11-07 09:40:05 +000078
Peter Smithf6775ea2018-12-18 12:40:19 +000079The ``build-c-flags`` need to be sufficient to pass the C-make compiler check,
80compile compiler-rt, and if you are running the tests, compile and link the
81tests. When cross-compiling with clang we will need to pass sufficient
82information to generate code for the Arm architecture we are targeting. We will
83need to select the Arm target, select the Armv7-A architecture and choose
84between using Arm or Thumb.
85instructions. For example:
Peter Smith51bcf5f2017-11-07 09:40:05 +000086
87* ``--target=arm-linux-gnueabihf``
Peter Smithf6775ea2018-12-18 12:40:19 +000088* ``-march=armv7a``
89* ``-mthumb``
90
91When using a GCC arm-linux-gnueabihf toolchain the following flags are
92needed to pick up the includes and libraries:
93
Peter Smith51bcf5f2017-11-07 09:40:05 +000094* ``--gcc-toolchain=/path/to/dir/toolchain``
95* ``--sysroot=/path/to/toolchain/arm-linux-gnueabihf/libc``
96
Peter Smithf6775ea2018-12-18 12:40:19 +000097In this example we will be adding all of the command line options to both
98``CMAKE_C_FLAGS`` and ``CMAKE_ASM_FLAGS``. There are cmake flags to pass some of
99these options individually which can be used to simplify the ``build-c-flags``:
100
101* ``-DCMAKE_C_COMPILER_TARGET="arm-linux-gnueabihf"``
102* ``-DCMAKE_ASM_COMPILER_TARGET="arm-linux-gnueabihf"``
103* ``-DCMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN=/path/to/dir/toolchain``
104* ``-DCMAKE_SYSROOT=/path/to/dir/toolchain/arm-linux-gnueabihf/libc``
Peter Smith51bcf5f2017-11-07 09:40:05 +0000105
106Once cmake has completed the builtins can be built with ``ninja builtins``
107
108Testing compiler-rt builtins using qemu-arm
109===========================================
110To test the builtins library we need to add a few more cmake flags to enable
111testing and set up the compiler and flags for test case. We must also tell
112cmake that we wish to run the tests on ``qemu-arm``.
113
114* ``-DCOMPILER_RT_EMULATOR="qemu-arm -L /path/to/armhf/sysroot``
115* ``-DCOMPILER_RT_INCLUDE_TESTS=ON``
116* ``-DCOMPILER_RT_TEST_COMPILER="/path/to/clang"``
117* ``-DCOMPILER_RT_TEST_COMPILER_CFLAGS="test-c-flags"``
118
119The ``/path/to/armhf/sysroot`` should be the same as the one passed to
120``--sysroot`` in the "build-c-flags".
121
Peter Smithf6775ea2018-12-18 12:40:19 +0000122The "test-c-flags" need to include the target, architecture, gcc-toolchain,
123sysroot and arm/thumb state. The additional cmake defines such as
124``CMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN`` do not apply when building the tests. If
125you have put all of these in "build-c-flags" then these can be repeated. If you
126wish to use lld to link the tests then add ``"-fuse-ld=lld``.
Peter Smith51bcf5f2017-11-07 09:40:05 +0000127
128Once cmake has completed the tests can be built and run using
129``ninja check-builtins``
130
Peter Smithf6775ea2018-12-18 12:40:19 +0000131Troubleshooting
132===============
133
134The cmake try compile stage fails
135---------------------------------
136At an early stage cmake will attempt to compile and link a simple C program to
137test if the toolchain is working.
138
139This stage can often fail at link time if the ``--sysroot`` and
140``--gcc-toolchain`` options are not passed to the compiler. Check the
141``CMAKE_C_FLAGS`` and ``CMAKE_C_COMPILER_TARGET`` flags.
142
143It can be useful to build a simple example outside of cmake with your toolchain
144to make sure it is working. For example: ``clang --target=arm-linux-gnueabi -march=armv7a --gcc-toolchain=/path/to/gcc-toolchain --sysroot=/path/to/gcc-toolchain/arm-linux-gnueabihf/libc helloworld.c``
145
146Clang uses the host header files
147--------------------------------
148On debian based systems it is possible to install multiarch support for
149arm-linux-gnueabi and arm-linux-gnueabihf. In many cases clang can successfully
150use this multiarch support when -gcc-toolchain and --sysroot are not supplied.
151Unfortunately clang adds ``/usr/local/include`` before
152``/usr/include/arm-linux-gnueabihf`` leading to errors when compiling the hosts
153header files.
154
155The multiarch support is not sufficient to build the builtins you will need to
156use a separate arm-linux-gnueabihf toolchain.
157
158No target passed to clang
159-------------------------
160If clang is not given a target it will typically use the host target, this will
161not understand the Arm assembly language files resulting in error messages such
162as ``error: unknown directive .syntax unified``.
163
164You can check the clang invocation in the error message to see if there is no
165``--target`` or if it is set incorrectly. The cause is usually
166``CMAKE_ASM_FLAGS`` not containing ``--target`` or ``CMAKE_ASM_COMPILER_TARGET`` not being present.
167
168Arm architecture not given
169--------------------------
170The ``--target=arm-linux-gnueabihf`` will default to arm architecture v4t which
171cannot assemble the barrier instructions used in the synch_and_fetch source
172files.
173
174The cause is usually a missing ``-march=armv7a`` from the ``CMAKE_ASM_FLAGS``.
175
176Compiler-rt builds but the tests fail to build
177----------------------------------------------
178The flags used to build the tests are not the same as those used to build the
179builtins. The c flags are provided by ``COMPILER_RT_TEST_COMPILE_CFLAGS`` and
180the ``CMAKE_C_COMPILER_TARGET``, ``CMAKE_ASM_COMPILER_TARGET``,
181``CMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN`` and ``CMAKE_SYSROOT`` flags are not
182applied.
183
184Make sure that ``COMPILER_RT_TEST_COMPILE_CFLAGS`` contains all the necessary
185information.
186
187
Peter Smith51bcf5f2017-11-07 09:40:05 +0000188Modifications for other Targets
189===============================
190
191Arm Soft-Float Target
192---------------------
193The instructions for the Arm hard-float target can be used for the soft-float
194target by substituting soft-float equivalents for the sysroot and target. The
195target to use is:
196
197* ``-DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabi``
198
199Depending on whether you want to use floating point instructions or not you
200may need extra c-flags such as ``-mfloat-abi=softfp`` for use of floating-point
201instructions, and ``-mfloat-abi=soft -mfpu=none`` for software floating-point
202emulation.
203
Peter Smithf6775ea2018-12-18 12:40:19 +0000204You will need to use an arm-linux-gnueabi GNU toolchain for soft-float.
205
Peter Smith51bcf5f2017-11-07 09:40:05 +0000206AArch64 Target
207--------------
208The instructions for Arm can be used for AArch64 by substituting AArch64
209equivalents for the sysroot, emulator and target.
210
211* ``-DCMAKE_C_COMPILER_TARGET=aarch64-linux-gnu``
212* ``-DCOMPILER_RT_EMULATOR="qemu-aarch64 -L /path/to/aarch64/sysroot``
213
214The CMAKE_C_FLAGS and COMPILER_RT_TEST_COMPILER_CFLAGS may also need:
215``"--sysroot=/path/to/aarch64/sysroot --gcc-toolchain=/path/to/gcc-toolchain"``
216
217Armv6-m, Armv7-m and Armv7E-M targets
218-------------------------------------
Peter Smith51bcf5f2017-11-07 09:40:05 +0000219To build and test the libraries using a similar method to Armv7-A is possible
220but more difficult. The main problems are:
221
222* There isn't a ``qemu-arm`` user-mode emulator for bare-metal systems. The ``qemu-system-arm`` can be used but this is significantly more difficult to setup.
Peter Smithf6775ea2018-12-18 12:40:19 +0000223* The targets to compile compiler-rt have the suffix -none-eabi. This uses the BareMetal driver in clang and by default won't find the libraries needed to pass the cmake compiler check.
Peter Smith51bcf5f2017-11-07 09:40:05 +0000224
225As the Armv6-M, Armv7-M and Armv7E-M builds of compiler-rt only use instructions
226that are supported on Armv7-A we can still get most of the value of running the
227tests using the same ``qemu-arm`` that we used for Armv7-A by building and
228running the test cases for Armv7-A but using the builtins compiled for
Peter Smithf6775ea2018-12-18 12:40:19 +0000229Armv6-M, Armv7-M or Armv7E-M. This will test that the builtins can be linked
230into a binary and execute the tests correctly but it will not catch if the
231builtins use instructions that are supported on Armv7-A but not Armv6-M,
232Armv7-M and Armv7E-M.
Peter Smith51bcf5f2017-11-07 09:40:05 +0000233
Peter Smithf6775ea2018-12-18 12:40:19 +0000234To get the cmake compile test to pass you will need to pass the libraries
235needed to successfully link the cmake test via ``CMAKE_CFLAGS``. It is
236strongly recommended that you use version 3.6 or above of cmake so you can use
Peter Smith51bcf5f2017-11-07 09:40:05 +0000237``CMAKE_TRY_COMPILE_TARGET=STATIC_LIBRARY`` to skip the link step.
238
239* ``-DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY``
240* ``-DCOMPILER_RT_OS_DIR="baremetal"``
241* ``-DCOMPILER_RT_BUILD_BUILTINS=ON``
242* ``-DCOMPILER_RT_BUILD_SANITIZERS=OFF``
243* ``-DCOMPILER_RT_BUILD_XRAY=OFF``
244* ``-DCOMPILER_RT_BUILD_LIBFUZZER=OFF``
245* ``-DCOMPILER_RT_BUILD_PROFILE=OFF``
246* ``-DCMAKE_C_COMPILER=${host_install_dir}/bin/clang``
247* ``-DCMAKE_C_COMPILER_TARGET="your *-none-eabi target"``
Peter Smithf6775ea2018-12-18 12:40:19 +0000248* ``-DCMAKE_ASM_COMPILER_TARGET="your *-none-eabi target"``
Peter Smith51bcf5f2017-11-07 09:40:05 +0000249* ``-DCMAKE_AR=/path/to/llvm-ar``
250* ``-DCMAKE_NM=/path/to/llvm-nm``
251* ``-DCMAKE_RANLIB=/path/to/llvm-ranlib``
252* ``-DCOMPILER_RT_BAREMETAL_BUILD=ON``
253* ``-DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON``
254* ``-DLLVM_CONFIG_PATH=/path/to/llvm-config``
255* ``-DCMAKE_C_FLAGS="build-c-flags"``
Peter Smithf6775ea2018-12-18 12:40:19 +0000256* ``-DCMAKE_ASM_FLAGS="build-c-flags"``
Peter Smith51bcf5f2017-11-07 09:40:05 +0000257* ``-DCOMPILER_RT_EMULATOR="qemu-arm -L /path/to/armv7-A/sysroot"``
258* ``-DCOMPILER_RT_INCLUDE_TESTS=ON``
259* ``-DCOMPILER_RT_TEST_COMPILER="/path/to/clang"``
260* ``-DCOMPILER_RT_TEST_COMPILER_CFLAGS="test-c-flags"``
261
262The Armv6-M builtins will use the soft-float ABI. When compiling the tests for
263Armv7-A we must include ``"-mthumb -mfloat-abi=soft -mfpu=none"`` in the
264test-c-flags. We must use an Armv7-A soft-float abi sysroot for ``qemu-arm``.
265
Peter Smith51bcf5f2017-11-07 09:40:05 +0000266Depending on the linker used for the test cases you may encounter BuildAttribute
267mismatches between the M-profile objects from compiler-rt and the A-profile
Peter Smithf6775ea2018-12-18 12:40:19 +0000268objects from the test. The lld linker does not check the profile
269BuildAttribute so it can be used to link the tests by adding -fuse-ld=lld to the
Peter Smith51bcf5f2017-11-07 09:40:05 +0000270``COMPILER_RT_TEST_COMPILER_CFLAGS``.
Peter Smithf6775ea2018-12-18 12:40:19 +0000271
272Alternative using a cmake cache
273-------------------------------
274If you wish to build, but not test compiler-rt for Armv6-M, Armv7-M or Armv7E-M
275the easiest way is to use the BaremetalARM.cmake recipe in clang/cmake/caches.
276
277You will need a bare metal sysroot such as that provided by the GNU ARM
278Embedded toolchain.
279
280The libraries can be built with the cmake options:
281
282* ``-DBAREMETAL_ARMV6M_SYSROOT=/path/to/bare/metal/toolchain/arm-none-eabi``
283* ``-DBAREMETAL_ARMV7M_SYSROOT=/path/to/bare/metal/toolchain/arm-none-eabi``
284* ``-DBAREMETAL_ARMV7EM_SYSROOT=/path/to/bare/metal/toolchain/arm-none-eabi``
285* ``-C /path/to/llvm/source/tools/clang/cmake/caches/BaremetalARM.cmake``
286* ``/path/to/llvm``
287
288**Note** that for the recipe to work the compiler-rt source must be checked out
289into the directory llvm/runtimes. You will also need clang and lld checked out.
290