Peter Smith | 51bcf5f | 2017-11-07 09:40:05 +0000 | [diff] [blame] | 1 | =================================================================== |
| 2 | How to Cross Compile Compiler-rt Builtins For Arm |
| 3 | =================================================================== |
| 4 | |
| 5 | Introduction |
| 6 | ============ |
| 7 | |
| 8 | This document contains information about building and testing the builtins part |
| 9 | of compiler-rt for an Arm target, from an x86_64 Linux machine. |
| 10 | |
| 11 | While this document concentrates on Arm and Linux the general principles should |
| 12 | apply to other targets supported by compiler-rt. Further contributions for other |
| 13 | targets are welcome. |
| 14 | |
| 15 | The instructions in this document depend on libraries and programs external to |
| 16 | LLVM, there are many ways to install and configure these dependencies so you |
| 17 | may need to adapt the instructions here to fit your own local situation. |
| 18 | |
| 19 | Prerequisites |
| 20 | ============= |
| 21 | |
Peter Smith | f6775ea | 2018-12-18 12:40:19 +0000 | [diff] [blame] | 22 | In this use case we'll be using cmake on a Debian-based Linux system, |
Peter Smith | 51bcf5f | 2017-11-07 09:40:05 +0000 | [diff] [blame] | 23 | cross-compiling from an x86_64 host to a hard-float Armv7-A target. We'll be |
| 24 | using as many of the LLVM tools as we can, but it is possible to use GNU |
| 25 | equivalents. |
| 26 | |
| 27 | * ``A build of LLVM/clang for the llvm-tools and llvm-config`` |
Peter Smith | f6775ea | 2018-12-18 12:40:19 +0000 | [diff] [blame] | 28 | * ``A clang executable with support for the ARM target`` |
| 29 | * ``compiler-rt sources`` |
Peter Smith | 51bcf5f | 2017-11-07 09:40:05 +0000 | [diff] [blame] | 30 | * ``The qemu-arm user mode emulator`` |
| 31 | * ``An arm-linux-gnueabihf sysroot`` |
| 32 | |
Peter Smith | f6775ea | 2018-12-18 12:40:19 +0000 | [diff] [blame] | 33 | In this example we will be using ninja. |
| 34 | |
Peter Smith | 51bcf5f | 2017-11-07 09:40:05 +0000 | [diff] [blame] | 35 | See https://compiler-rt.llvm.org/ for more information about the dependencies |
| 36 | on clang and LLVM. |
| 37 | |
Peter Smith | f6775ea | 2018-12-18 12:40:19 +0000 | [diff] [blame] | 38 | See https://llvm.org/docs/GettingStarted.html for information about obtaining |
| 39 | the source for LLVM and compiler-rt. Note that the getting started guide |
| 40 | places compiler-rt in the projects subdirectory, but this is not essential and |
| 41 | if you are using the BaremetalARM.cmake cache for v6-M, v7-M and v7-EM then |
| 42 | compiler-rt must be placed in the runtimes directory. |
| 43 | |
Peter Smith | 51bcf5f | 2017-11-07 09:40:05 +0000 | [diff] [blame] | 44 | ``qemu-arm`` should be available as a package for your Linux distribution. |
| 45 | |
| 46 | The most complicated of the prequisites to satisfy is the arm-linux-gnueabihf |
Peter Smith | f6775ea | 2018-12-18 12:40:19 +0000 | [diff] [blame] | 47 | sysroot. In theory it is possible to use the Linux distributions multiarch |
| 48 | support to fulfill the dependencies for building but unfortunately due to |
| 49 | /usr/local/include being added some host includes are selected. The easiest way |
| 50 | to supply a sysroot is to download the arm-linux-gnueabihf toolchain. This can |
| 51 | be 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 Smith | 51bcf5f | 2017-11-07 09:40:05 +0000 | [diff] [blame] | 54 | |
| 55 | Building compiler-rt builtins for Arm |
| 56 | ===================================== |
| 57 | We will be doing a standalone build of compiler-rt using the following cmake |
| 58 | options. |
| 59 | |
Peter Smith | f6775ea | 2018-12-18 12:40:19 +0000 | [diff] [blame] | 60 | * ``path/to/compiler-rt`` |
| 61 | * ``-G Ninja`` |
Peter Smith | 51bcf5f | 2017-11-07 09:40:05 +0000 | [diff] [blame] | 62 | * ``-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 Smith | f6775ea | 2018-12-18 12:40:19 +0000 | [diff] [blame] | 73 | * ``-DCMAKE_ASM_COMPILER_TARGET="arm-linux-gnueabihf"`` |
Peter Smith | 51bcf5f | 2017-11-07 09:40:05 +0000 | [diff] [blame] | 74 | * ``-DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON`` |
| 75 | * ``-DLLVM_CONFIG_PATH=/path/to/llvm-config`` |
| 76 | * ``-DCMAKE_C_FLAGS="build-c-flags"`` |
Peter Smith | f6775ea | 2018-12-18 12:40:19 +0000 | [diff] [blame] | 77 | * ``-DCMAKE_ASM_FLAGS="build-c-flags"`` |
Peter Smith | 51bcf5f | 2017-11-07 09:40:05 +0000 | [diff] [blame] | 78 | |
Peter Smith | f6775ea | 2018-12-18 12:40:19 +0000 | [diff] [blame] | 79 | The ``build-c-flags`` need to be sufficient to pass the C-make compiler check, |
| 80 | compile compiler-rt, and if you are running the tests, compile and link the |
| 81 | tests. When cross-compiling with clang we will need to pass sufficient |
| 82 | information to generate code for the Arm architecture we are targeting. We will |
| 83 | need to select the Arm target, select the Armv7-A architecture and choose |
| 84 | between using Arm or Thumb. |
| 85 | instructions. For example: |
Peter Smith | 51bcf5f | 2017-11-07 09:40:05 +0000 | [diff] [blame] | 86 | |
| 87 | * ``--target=arm-linux-gnueabihf`` |
Peter Smith | f6775ea | 2018-12-18 12:40:19 +0000 | [diff] [blame] | 88 | * ``-march=armv7a`` |
| 89 | * ``-mthumb`` |
| 90 | |
| 91 | When using a GCC arm-linux-gnueabihf toolchain the following flags are |
| 92 | needed to pick up the includes and libraries: |
| 93 | |
Peter Smith | 51bcf5f | 2017-11-07 09:40:05 +0000 | [diff] [blame] | 94 | * ``--gcc-toolchain=/path/to/dir/toolchain`` |
| 95 | * ``--sysroot=/path/to/toolchain/arm-linux-gnueabihf/libc`` |
| 96 | |
Peter Smith | f6775ea | 2018-12-18 12:40:19 +0000 | [diff] [blame] | 97 | In 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 |
| 99 | these 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 Smith | 51bcf5f | 2017-11-07 09:40:05 +0000 | [diff] [blame] | 105 | |
| 106 | Once cmake has completed the builtins can be built with ``ninja builtins`` |
| 107 | |
| 108 | Testing compiler-rt builtins using qemu-arm |
| 109 | =========================================== |
| 110 | To test the builtins library we need to add a few more cmake flags to enable |
| 111 | testing and set up the compiler and flags for test case. We must also tell |
| 112 | cmake 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 | |
| 119 | The ``/path/to/armhf/sysroot`` should be the same as the one passed to |
| 120 | ``--sysroot`` in the "build-c-flags". |
| 121 | |
Peter Smith | f6775ea | 2018-12-18 12:40:19 +0000 | [diff] [blame] | 122 | The "test-c-flags" need to include the target, architecture, gcc-toolchain, |
| 123 | sysroot and arm/thumb state. The additional cmake defines such as |
| 124 | ``CMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN`` do not apply when building the tests. If |
| 125 | you have put all of these in "build-c-flags" then these can be repeated. If you |
| 126 | wish to use lld to link the tests then add ``"-fuse-ld=lld``. |
Peter Smith | 51bcf5f | 2017-11-07 09:40:05 +0000 | [diff] [blame] | 127 | |
| 128 | Once cmake has completed the tests can be built and run using |
| 129 | ``ninja check-builtins`` |
| 130 | |
Peter Smith | f6775ea | 2018-12-18 12:40:19 +0000 | [diff] [blame] | 131 | Troubleshooting |
| 132 | =============== |
| 133 | |
| 134 | The cmake try compile stage fails |
| 135 | --------------------------------- |
| 136 | At an early stage cmake will attempt to compile and link a simple C program to |
| 137 | test if the toolchain is working. |
| 138 | |
| 139 | This 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 | |
| 143 | It can be useful to build a simple example outside of cmake with your toolchain |
| 144 | to 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 | |
| 146 | Clang uses the host header files |
| 147 | -------------------------------- |
| 148 | On debian based systems it is possible to install multiarch support for |
| 149 | arm-linux-gnueabi and arm-linux-gnueabihf. In many cases clang can successfully |
| 150 | use this multiarch support when -gcc-toolchain and --sysroot are not supplied. |
| 151 | Unfortunately clang adds ``/usr/local/include`` before |
| 152 | ``/usr/include/arm-linux-gnueabihf`` leading to errors when compiling the hosts |
| 153 | header files. |
| 154 | |
| 155 | The multiarch support is not sufficient to build the builtins you will need to |
| 156 | use a separate arm-linux-gnueabihf toolchain. |
| 157 | |
| 158 | No target passed to clang |
| 159 | ------------------------- |
| 160 | If clang is not given a target it will typically use the host target, this will |
| 161 | not understand the Arm assembly language files resulting in error messages such |
| 162 | as ``error: unknown directive .syntax unified``. |
| 163 | |
| 164 | You 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 | |
| 168 | Arm architecture not given |
| 169 | -------------------------- |
| 170 | The ``--target=arm-linux-gnueabihf`` will default to arm architecture v4t which |
| 171 | cannot assemble the barrier instructions used in the synch_and_fetch source |
| 172 | files. |
| 173 | |
| 174 | The cause is usually a missing ``-march=armv7a`` from the ``CMAKE_ASM_FLAGS``. |
| 175 | |
| 176 | Compiler-rt builds but the tests fail to build |
| 177 | ---------------------------------------------- |
| 178 | The flags used to build the tests are not the same as those used to build the |
| 179 | builtins. The c flags are provided by ``COMPILER_RT_TEST_COMPILE_CFLAGS`` and |
| 180 | the ``CMAKE_C_COMPILER_TARGET``, ``CMAKE_ASM_COMPILER_TARGET``, |
| 181 | ``CMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN`` and ``CMAKE_SYSROOT`` flags are not |
| 182 | applied. |
| 183 | |
| 184 | Make sure that ``COMPILER_RT_TEST_COMPILE_CFLAGS`` contains all the necessary |
| 185 | information. |
| 186 | |
| 187 | |
Peter Smith | 51bcf5f | 2017-11-07 09:40:05 +0000 | [diff] [blame] | 188 | Modifications for other Targets |
| 189 | =============================== |
| 190 | |
| 191 | Arm Soft-Float Target |
| 192 | --------------------- |
| 193 | The instructions for the Arm hard-float target can be used for the soft-float |
| 194 | target by substituting soft-float equivalents for the sysroot and target. The |
| 195 | target to use is: |
| 196 | |
| 197 | * ``-DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabi`` |
| 198 | |
| 199 | Depending on whether you want to use floating point instructions or not you |
| 200 | may need extra c-flags such as ``-mfloat-abi=softfp`` for use of floating-point |
| 201 | instructions, and ``-mfloat-abi=soft -mfpu=none`` for software floating-point |
| 202 | emulation. |
| 203 | |
Peter Smith | f6775ea | 2018-12-18 12:40:19 +0000 | [diff] [blame] | 204 | You will need to use an arm-linux-gnueabi GNU toolchain for soft-float. |
| 205 | |
Peter Smith | 51bcf5f | 2017-11-07 09:40:05 +0000 | [diff] [blame] | 206 | AArch64 Target |
| 207 | -------------- |
| 208 | The instructions for Arm can be used for AArch64 by substituting AArch64 |
| 209 | equivalents 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 | |
| 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"`` |
| 216 | |
| 217 | Armv6-m, Armv7-m and Armv7E-M targets |
| 218 | ------------------------------------- |
Peter Smith | 51bcf5f | 2017-11-07 09:40:05 +0000 | [diff] [blame] | 219 | To build and test the libraries using a similar method to Armv7-A is possible |
| 220 | but 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 Smith | f6775ea | 2018-12-18 12:40:19 +0000 | [diff] [blame] | 223 | * 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 Smith | 51bcf5f | 2017-11-07 09:40:05 +0000 | [diff] [blame] | 224 | |
| 225 | As the Armv6-M, Armv7-M and Armv7E-M builds of compiler-rt only use instructions |
| 226 | that are supported on Armv7-A we can still get most of the value of running the |
| 227 | tests using the same ``qemu-arm`` that we used for Armv7-A by building and |
| 228 | running the test cases for Armv7-A but using the builtins compiled for |
Peter Smith | f6775ea | 2018-12-18 12:40:19 +0000 | [diff] [blame] | 229 | Armv6-M, Armv7-M or Armv7E-M. This will test that the builtins can be linked |
| 230 | into a binary and execute the tests correctly but it will not catch if the |
| 231 | builtins use instructions that are supported on Armv7-A but not Armv6-M, |
| 232 | Armv7-M and Armv7E-M. |
Peter Smith | 51bcf5f | 2017-11-07 09:40:05 +0000 | [diff] [blame] | 233 | |
Peter Smith | f6775ea | 2018-12-18 12:40:19 +0000 | [diff] [blame] | 234 | To get the cmake compile test to pass you will need to pass the libraries |
| 235 | needed to successfully link the cmake test via ``CMAKE_CFLAGS``. It is |
| 236 | strongly recommended that you use version 3.6 or above of cmake so you can use |
Peter Smith | 51bcf5f | 2017-11-07 09:40:05 +0000 | [diff] [blame] | 237 | ``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 Smith | f6775ea | 2018-12-18 12:40:19 +0000 | [diff] [blame] | 248 | * ``-DCMAKE_ASM_COMPILER_TARGET="your *-none-eabi target"`` |
Peter Smith | 51bcf5f | 2017-11-07 09:40:05 +0000 | [diff] [blame] | 249 | * ``-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 Smith | f6775ea | 2018-12-18 12:40:19 +0000 | [diff] [blame] | 256 | * ``-DCMAKE_ASM_FLAGS="build-c-flags"`` |
Peter Smith | 51bcf5f | 2017-11-07 09:40:05 +0000 | [diff] [blame] | 257 | * ``-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 | |
| 262 | The Armv6-M builtins will use the soft-float ABI. When compiling the tests for |
| 263 | Armv7-A we must include ``"-mthumb -mfloat-abi=soft -mfpu=none"`` in the |
| 264 | test-c-flags. We must use an Armv7-A soft-float abi sysroot for ``qemu-arm``. |
| 265 | |
Peter Smith | 51bcf5f | 2017-11-07 09:40:05 +0000 | [diff] [blame] | 266 | Depending on the linker used for the test cases you may encounter BuildAttribute |
| 267 | mismatches between the M-profile objects from compiler-rt and the A-profile |
Peter Smith | f6775ea | 2018-12-18 12:40:19 +0000 | [diff] [blame] | 268 | objects from the test. The lld linker does not check the profile |
| 269 | BuildAttribute so it can be used to link the tests by adding -fuse-ld=lld to the |
Peter Smith | 51bcf5f | 2017-11-07 09:40:05 +0000 | [diff] [blame] | 270 | ``COMPILER_RT_TEST_COMPILER_CFLAGS``. |
Peter Smith | f6775ea | 2018-12-18 12:40:19 +0000 | [diff] [blame] | 271 | |
| 272 | Alternative using a cmake cache |
| 273 | ------------------------------- |
| 274 | If you wish to build, but not test compiler-rt for Armv6-M, Armv7-M or Armv7E-M |
| 275 | the easiest way is to use the BaremetalARM.cmake recipe in clang/cmake/caches. |
| 276 | |
| 277 | You will need a bare metal sysroot such as that provided by the GNU ARM |
| 278 | Embedded toolchain. |
| 279 | |
| 280 | The 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 |
| 289 | into the directory llvm/runtimes. You will also need clang and lld checked out. |
| 290 | |