|
| 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 | + |
| 22 | +In this use case we'll be using CMake on a Debian-based Linux system, |
| 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`` |
| 28 | + * ``The qemu-arm user mode emulator`` |
| 29 | + * ``An arm-linux-gnueabihf sysroot`` |
| 30 | + |
| 31 | +See https://compiler-rt.llvm.org/ for more information about the dependencies |
| 32 | +on clang and LLVM. |
| 33 | + |
| 34 | +``qemu-arm`` should be available as a package for your Linux distribution. |
| 35 | + |
| 36 | +The most complicated of the prequisites to satisfy is the arm-linux-gnueabihf |
| 37 | +sysroot. The :doc:`HowToCrossCompileLLVM` has information about how to use the |
| 38 | +Linux distributions multiarch support to fulfill the dependencies for building |
| 39 | +LLVM. Alternatively, as building and testing just the compiler-rt builtins |
| 40 | +requires fewer dependencies than LLVM, it is possible to use the Linaro |
| 41 | +arm-linux-gnueabihf gcc installation as our sysroot. |
| 42 | + |
| 43 | +Building compiler-rt builtins for Arm |
| 44 | +===================================== |
| 45 | +We will be doing a standalone build of compiler-rt using the following cmake |
| 46 | +options. |
| 47 | + |
| 48 | +* ``path/to/llvm/projects/compiler-rt`` |
| 49 | +* ``-DCOMPILER_RT_BUILD_BUILTINS=ON`` |
| 50 | +* ``-DCOMPILER_RT_BUILD_SANITIZERS=OFF`` |
| 51 | +* ``-DCOMPILER_RT_BUILD_XRAY=OFF`` |
| 52 | +* ``-DCOMPILER_RT_BUILD_LIBFUZZER=OFF`` |
| 53 | +* ``-DCOMPILER_RT_BUILD_PROFILE=OFF`` |
| 54 | +* ``-DCMAKE_C_COMPILER=/path/to/clang`` |
| 55 | +* ``-DCMAKE_AR=/path/to/llvm-ar`` |
| 56 | +* ``-DCMAKE_NM=/path/to/llvm-nm`` |
| 57 | +* ``-DCMAKE_RANLIB=/path/to/llvm-ranlib`` |
| 58 | +* ``-DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=lld"`` |
| 59 | +* ``-DCMAKE_C_COMPILER_TARGET="arm-linux-gnueabihf"`` |
| 60 | +* ``-DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON`` |
| 61 | +* ``-DLLVM_CONFIG_PATH=/path/to/llvm-config`` |
| 62 | +* ``-DCMAKE_C_FLAGS="build-c-flags"`` |
| 63 | + |
| 64 | +The build-c-flags need to be sufficient to pass the C-make compiler check and |
| 65 | +to compile compiler-rt. When using a GCC 7 Linaro arm-linux-gnueabihf |
| 66 | +installation the following flags are needed: |
| 67 | + |
| 68 | +* ``--target=arm-linux-gnueabihf`` |
| 69 | +* ``--march=armv7a`` |
| 70 | +* ``--gcc-toolchain=/path/to/dir/toolchain`` |
| 71 | +* ``--sysroot=/path/to/toolchain/arm-linux-gnueabihf/libc`` |
| 72 | + |
| 73 | +Depending on how your sysroot is laid out, you may not need ``--gcc-toolchain``. |
| 74 | +For example if you have added armhf as an architecture using your Linux |
| 75 | +distributions multiarch support then you should be able to use ``--sysroot=/``. |
| 76 | + |
| 77 | +Once cmake has completed the builtins can be built with ``ninja builtins`` |
| 78 | + |
| 79 | +Testing compiler-rt builtins using qemu-arm |
| 80 | +=========================================== |
| 81 | +To test the builtins library we need to add a few more cmake flags to enable |
| 82 | +testing and set up the compiler and flags for test case. We must also tell |
| 83 | +cmake that we wish to run the tests on ``qemu-arm``. |
| 84 | + |
| 85 | +* ``-DCOMPILER_RT_EMULATOR="qemu-arm -L /path/to/armhf/sysroot`` |
| 86 | +* ``-DCOMPILER_RT_INCLUDE_TESTS=ON`` |
| 87 | +* ``-DCOMPILER_RT_TEST_COMPILER="/path/to/clang"`` |
| 88 | +* ``-DCOMPILER_RT_TEST_COMPILER_CFLAGS="test-c-flags"`` |
| 89 | + |
| 90 | +The ``/path/to/armhf/sysroot`` should be the same as the one passed to |
| 91 | +``--sysroot`` in the "build-c-flags". |
| 92 | + |
| 93 | +The "test-c-flags" can be the same as the "build-c-flags", with the addition |
| 94 | +of ``"-fuse-ld=lld`` if you wish to use lld to link the tests. |
| 95 | + |
| 96 | +Once cmake has completed the tests can be built and run using |
| 97 | +``ninja check-builtins`` |
| 98 | + |
| 99 | +Modifications for other Targets |
| 100 | +=============================== |
| 101 | + |
| 102 | +Arm Soft-Float Target |
| 103 | +--------------------- |
| 104 | +The instructions for the Arm hard-float target can be used for the soft-float |
| 105 | +target by substituting soft-float equivalents for the sysroot and target. The |
| 106 | +target to use is: |
| 107 | + |
| 108 | +* ``-DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabi`` |
| 109 | + |
| 110 | +Depending on whether you want to use floating point instructions or not you |
| 111 | +may need extra c-flags such as ``-mfloat-abi=softfp`` for use of floating-point |
| 112 | +instructions, and ``-mfloat-abi=soft -mfpu=none`` for software floating-point |
| 113 | +emulation. |
| 114 | + |
| 115 | +AArch64 Target |
| 116 | +-------------- |
| 117 | +The instructions for Arm can be used for AArch64 by substituting AArch64 |
| 118 | +equivalents for the sysroot, emulator and target. |
| 119 | + |
| 120 | +* ``-DCMAKE_C_COMPILER_TARGET=aarch64-linux-gnu`` |
| 121 | +* ``-DCOMPILER_RT_EMULATOR="qemu-aarch64 -L /path/to/aarch64/sysroot`` |
| 122 | + |
| 123 | +The CMAKE_C_FLAGS and COMPILER_RT_TEST_COMPILER_CFLAGS may also need: |
| 124 | +``"--sysroot=/path/to/aarch64/sysroot --gcc-toolchain=/path/to/gcc-toolchain"`` |
| 125 | + |
| 126 | +Armv6-m, Armv7-m and Armv7E-M targets |
| 127 | +------------------------------------- |
| 128 | +If you wish to build, but not test compiler-rt for Armv6-M, Armv7-M or Armv7E-M |
| 129 | +then the easiest way is to use the BaremetalARM.cmake recipe in |
| 130 | +clang/cmake/caches. |
| 131 | + |
| 132 | +You will need a bare metal sysroot such as that provided by the GNU ARM |
| 133 | +Embedded toolchain. |
| 134 | + |
| 135 | +The libraries can be built with the cmake options: |
| 136 | + |
| 137 | +* ``-DBAREMETAL_ARMV6M_SYSROOT=/path/to/bare/metal/sysroot`` |
| 138 | +* ``-DBAREMETAL_ARMV7M_SYSROOT=/path/to/bare/metal/sysroot`` |
| 139 | +* ``-DBAREMETAL_ARMV7EM_SYSROOT=/path/to/bare/metal/sysroot`` |
| 140 | +* ``-C /path/to/llvm/source/tools/clang/cmake/caches/BaremetalARM.cmake`` |
| 141 | + |
| 142 | +**Note** that for the recipe to work the compiler-rt source must be checked out |
| 143 | +into the directory llvm/runtimes and not llvm/projects. |
| 144 | + |
| 145 | +To build and test the libraries using a similar method to Armv7-A is possible |
| 146 | +but more difficult. The main problems are: |
| 147 | + |
| 148 | +* 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. |
| 149 | +* The target 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. |
| 150 | + |
| 151 | +As the Armv6-M, Armv7-M and Armv7E-M builds of compiler-rt only use instructions |
| 152 | +that are supported on Armv7-A we can still get most of the value of running the |
| 153 | +tests using the same ``qemu-arm`` that we used for Armv7-A by building and |
| 154 | +running the test cases for Armv7-A but using the builtins compiled for |
| 155 | +Armv6-M, Armv7-M or Armv7E-M. This will not catch instructions that are |
| 156 | +supported on Armv7-A but not Armv6-M, Armv7-M and Armv7E-M. |
| 157 | + |
| 158 | +To get the cmake compile test to pass the libraries needed to successfully link |
| 159 | +the test application will need to be manually added to ``CMAKE_CFLAGS``. |
| 160 | +Alternatively if you are using version 3.6 or above of cmake you can use |
| 161 | +``CMAKE_TRY_COMPILE_TARGET=STATIC_LIBRARY`` to skip the link step. |
| 162 | + |
| 163 | +* ``-DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY`` |
| 164 | +* ``-DCOMPILER_RT_OS_DIR="baremetal"`` |
| 165 | +* ``-DCOMPILER_RT_BUILD_BUILTINS=ON`` |
| 166 | +* ``-DCOMPILER_RT_BUILD_SANITIZERS=OFF`` |
| 167 | +* ``-DCOMPILER_RT_BUILD_XRAY=OFF`` |
| 168 | +* ``-DCOMPILER_RT_BUILD_LIBFUZZER=OFF`` |
| 169 | +* ``-DCOMPILER_RT_BUILD_PROFILE=OFF`` |
| 170 | +* ``-DCMAKE_C_COMPILER=${host_install_dir}/bin/clang`` |
| 171 | +* ``-DCMAKE_C_COMPILER_TARGET="your *-none-eabi target"`` |
| 172 | +* ``-DCMAKE_AR=/path/to/llvm-ar`` |
| 173 | +* ``-DCMAKE_NM=/path/to/llvm-nm`` |
| 174 | +* ``-DCMAKE_RANLIB=/path/to/llvm-ranlib`` |
| 175 | +* ``-DCOMPILER_RT_BAREMETAL_BUILD=ON`` |
| 176 | +* ``-DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON`` |
| 177 | +* ``-DLLVM_CONFIG_PATH=/path/to/llvm-config`` |
| 178 | +* ``-DCMAKE_C_FLAGS="build-c-flags"`` |
| 179 | +* ``-DCMAKE_ASM_FLAGS="${arm_cflags}"`` |
| 180 | +* ``-DCOMPILER_RT_EMULATOR="qemu-arm -L /path/to/armv7-A/sysroot"`` |
| 181 | +* ``-DCOMPILER_RT_INCLUDE_TESTS=ON`` |
| 182 | +* ``-DCOMPILER_RT_TEST_COMPILER="/path/to/clang"`` |
| 183 | +* ``-DCOMPILER_RT_TEST_COMPILER_CFLAGS="test-c-flags"`` |
| 184 | + |
| 185 | +The Armv6-M builtins will use the soft-float ABI. When compiling the tests for |
| 186 | +Armv7-A we must include ``"-mthumb -mfloat-abi=soft -mfpu=none"`` in the |
| 187 | +test-c-flags. We must use an Armv7-A soft-float abi sysroot for ``qemu-arm``. |
| 188 | + |
| 189 | +Unfortunately at time of writing the Armv7-M and Armv7E-M builds of |
| 190 | +compiler-rt will always include assembler files including floating point |
| 191 | +instructions. This means that building for a cpu without a floating point unit |
| 192 | +requires something like removing the arm_Thumb1_VFPv2_SOURCES from the |
| 193 | +arm_Thumb1_SOURCES in builtins/CMakeLists.txt. The float-abi of the compiler-rt |
| 194 | +library must be matched by the float abi of the Armv7-A sysroot used by |
| 195 | +qemu-arm. |
| 196 | + |
| 197 | +Depending on the linker used for the test cases you may encounter BuildAttribute |
| 198 | +mismatches between the M-profile objects from compiler-rt and the A-profile |
| 199 | +objects from the test. The lld linker does not check the BuildAttributes so it |
| 200 | +can be used to link the tests by adding -fuse-ld=lld to the |
| 201 | +``COMPILER_RT_TEST_COMPILER_CFLAGS``. |
0 commit comments