204 lines · plain
1===================================================================2Cross-compilation using Clang3===================================================================4 5Introduction6============7 8This document will guide you in choosing the right Clang options9for cross-compiling your code to a different architecture. It assumes you10already know how to compile the code in question for the host architecture,11and that you know how to choose additional include and library paths.12 13However, this document is *not* a "how to" and won't help you setting your14build system or Makefiles, nor choosing the right CMake options, etc.15Also, it does not cover all the possible options, nor does it contain16specific examples for specific architectures. For a concrete example, the17`instructions for cross-compiling LLVM itself18<https://llvm.org/docs/HowToCrossCompileLLVM.html>`_ may be of interest.19 20After reading this document, you should be familiar with the main issues21related to cross-compilation, and what main compiler options Clang provides22for performing cross-compilation.23 24Cross compilation issues25========================26 27In GCC world, every host/target combination has its own set of binaries,28headers, libraries, etc. So, it's usually simple to download a package29with all files in, unzip to a directory and point the build system to30that compiler, that will know about its location and find all it needs to31when compiling your code.32 33On the other hand, Clang/LLVM is natively a cross-compiler, meaning that34one set of programs can compile to all targets by setting the ``-target``35option. That makes it a lot easier for programmers wishing to compile to36different platforms and architectures, and for compiler developers that37only have to maintain one build system, and for OS distributions, that38need only one set of main packages.39 40But, as is true to any cross-compiler, and given the complexity of41different architectures, OS's and options, it's not always easy finding42the headers, libraries or binutils to generate target specific code.43So you'll need special options to help Clang understand what target44you're compiling to, where your tools are, etc.45 46Another problem is that compilers come with standard libraries only (like47``compiler-rt``, ``libcxx``, ``libgcc``, ``libm``, etc), so you'll have to48find and make available to the build system, every other library required49to build your software, that is specific to your target. It's not enough to50have your host's libraries installed.51 52Finally, not all toolchains are the same, and consequently, not every Clang53option will work magically. Some options, like ``--sysroot`` (which54effectively changes the logical root for headers and libraries), assume55all your binaries and libraries are in the same directory, which may not56true when your cross-compiler was installed by the distribution's package57management. So, for each specific case, you may use more than one58option, and in most cases, you'll end up setting include paths (``-I``) and59library paths (``-L``) manually.60 61To sum up, different toolchains can:62 * be host/target specific or more flexible63 * be in a single directory, or spread out across your system64 * have different sets of libraries and headers by default65 * need special options, which your build system won't be able to figure66 out by itself67 68General Cross-Compilation Options in Clang69==========================================70 71Target Triple72-------------73 74The basic option is to define the target architecture. For that, use75``-target <triple>``. If you don't specify the target, CPU names won't76match (since Clang assumes the host triple), and the compilation will77go ahead, creating code for the host platform, which will break later78on when assembling or linking.79 80The triple has the general format ``<arch><sub>-<vendor>-<sys>-<env>``, where:81 * ``arch`` = ``x86_64``, ``i386``, ``arm``, ``thumb``, ``mips``, etc.82 * ``sub`` = for ex. on ARM: ``v5``, ``v6m``, ``v7a``, ``v7m``, etc.83 * ``vendor`` = ``pc``, ``apple``, ``nvidia``, ``ibm``, etc.84 * ``sys`` = ``none``, ``linux``, ``win32``, ``darwin``, ``cuda``, etc.85 * ``env`` = ``eabi``, ``gnu``, ``android``, ``macho``, ``elf``, etc.86 87The sub-architecture options are available for their own architectures,88of course, so "x86v7a" doesn't make sense. The vendor needs to be89specified only if there's a relevant change, for instance between PC90and Apple. Most of the time it can be omitted (and Unknown)91will be assumed, which sets the defaults for the specified architecture.92The system name is generally the OS (linux, darwin), but could be special93like the bare-metal "none".94 95When a parameter is not important, it can be omitted, or you can96choose ``unknown`` and the defaults will be used. If you choose a parameter97that Clang doesn't know, like ``blerg``, it'll ignore and assume98``unknown``, which is not always desired, so be careful.99 100Finally, the env (environment) option is something that will pick default101CPU/FPU, define the specific behaviour of your code (PCS, extensions),102and also choose the correct library calls, etc.103 104CPU, FPU, ABI105-------------106 107Once your target is specified, it's time to pick the hardware you'll108be compiling to. For every architecture, a default set of CPU/FPU/ABI109will be chosen, so you'll almost always have to change it via flags.110 111Typical flags include:112 * ``-mcpu=<cpu-name>``, like x86-64, swift, cortex-a15113 * ``-mfpu=<fpu-name>``, like SSE3, NEON, controlling the FP unit available114 * ``-mfloat-abi=<fabi>``, like soft, hard, controlling which registers115 to use for floating-point116 117The default is normally the common denominator, so that Clang doesn't118generate code that breaks. But that also means you won't get the best119code for your specific hardware, which may mean orders of magnitude120slower than you expect.121 122For example, if your target is ``arm-none-eabi``, the default CPU will123be ``arm7tdmi`` using soft float, which is extremely slow on modern cores,124whereas if your triple is ``armv7a-none-eabi``, it'll be Cortex-A8 with125NEON, but still using soft-float, which is much better, but still not126great.127 128Toolchain Options129-----------------130 131There are three main options to control access to your cross-compiler:132``--sysroot``, ``-I``, and ``-L``. The two last ones are well known,133but they're particularly important for additional libraries134and headers that are specific to your target.135 136There are two main ways to have a cross-compiler:137 138#. When you have extracted your cross-compiler from a zip file into139 a directory, you have to use ``--sysroot=<path>``. The path is the140 root directory where you have unpacked your file, and Clang will141 look for the directories ``bin``, ``lib``, ``include`` in there.142 143 In this case, your setup should be pretty much done (if no144 additional headers or libraries are needed), as Clang will find145 all binaries it needs (assembler, linker, etc) in there.146 147#. When you have installed via a package manager (modern Linux148 distributions have cross-compiler packages available), make149 sure the target triple you set is *also* the prefix of your150 cross-compiler toolchain.151 152 In this case, Clang will find the other binaries (assembler,153 linker), but not always where the target headers and libraries154 are. People add system-specific clues to Clang often, but as155 things change, it's more likely that it won't find than the156 other way around.157 158 So, here, you'll be a lot safer if you specify the include/library159 directories manually (via ``-I`` and ``-L``).160 161Target-Specific Libraries162=========================163 164All libraries that you compile as part of your build will be165cross-compiled to your target, and your build system will probably166find them in the right place. But all dependencies that are167normally checked against (like ``libxml`` or ``libz`` etc) will match168against the host platform, not the target.169 170So, if the build system is not aware that you want to cross-compile171your code, it will get every dependency wrong, and your compilation172will fail during build time, not configure time.173 174Also, finding the libraries for your target are not as easy175as for your host machine. There aren't many cross-libraries available176as packages to most OS's, so you'll have to either cross-compile them177from source, or download the package for your target platform,178extract the libraries and headers, put them in specific directories179and add ``-I`` and ``-L`` pointing to them.180 181Also, some libraries have different dependencies on different targets,182so configuration tools to find dependencies in the host can get the183list wrong for the target platform. This means that the configuration184of your build can get things wrong when setting their own library185paths, and you'll have to augment it via additional flags (configure,186Make, CMake, etc).187 188Multilibs189---------190 191When you want to cross-compile to more than one configuration, for192example hard-float-ARM and soft-float-ARM, you'll have to have multiple193copies of your libraries and (possibly) headers.194 195Some Linux distributions have support for Multilib, which handle that196for you in an easier way, but if you're not careful and, for instance,197forget to specify ``-ccc-gcc-name armv7l-linux-gnueabihf-gcc`` (which198uses hard-float), Clang will pick the ``armv7l-linux-gnueabi-ld``199(which uses soft-float) and linker errors will happen.200 201The same is true if you're compiling for different environments, like202``gnueabi`` and ``androideabi``, and might even link and run, but produce203run-time errors, which are much harder to track down and fix.204