From f54e02f969d02d640103db73efc30c45439fceab Mon Sep 17 00:00:00 2001 From: Renato Golin Date: Sun, 8 Sep 2013 20:44:39 +0000 Subject: [PATCH] Adding cross-compilation instructions to Clang git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@190281 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/CrossCompilation.rst | 203 ++++++++++++++++++++++++++++++++++++++ docs/index.rst | 1 + 2 files changed, 204 insertions(+) create mode 100644 docs/CrossCompilation.rst diff --git a/docs/CrossCompilation.rst b/docs/CrossCompilation.rst new file mode 100644 index 0000000000..b9de0ae382 --- /dev/null +++ b/docs/CrossCompilation.rst @@ -0,0 +1,203 @@ +=================================================================== +Cross-compilation using Clang/LLVM +=================================================================== + +Introduction +============ + +This document will guide you in choosing the right cross-compilation options +to hopefully help you target your code to a different architecture. It assumes +you already know how to compile the code in question for the host architecture, +and that you know how to choose additional include and library paths. + +However, this document is `not` a `HowTo` and wont help you setting your build +system or Makefiles, nor choosing the right CMake options. Also, it does not +cover all the possible options, nor it contains specific examples for specific +architectures. There are other documents in LLVM that do that in greater +details (ex. http://llvm.org/docs/HowToCrossCompileLLVM.html). + +After reading this document, you should be familiar with the main issues +related to, and what main compiler options Clang provides for performing +cross-compilation. + +Cross compilation issues +======================== + +In GCC world, every host/target combination has its own set of binaries, +headers, libraries, etc. So, it's usually simple to download a package +with all files in, unzip to a directory and point the build system to +that compiler, that will know about its location and find all it needs to +when compiling your code. + +On the other hand, Clang/LLVM is natively a cross-compiler, meaning that +one set of programs can compile to all targets by setting the -target +option. That makes it a lot easier to programers wishing to compile to +different platforms and architectures, and to compiler developers that +only have to maintain one build system, and to OS distributions, that +need only one set of main packages. + +But, as is true to any cross-compiler, and given the complexity of +different architectures, OSs and options, it's not always easy finding +the headers, libraries or binutils to generate target specific code. +So you'll need special options to help Clang understand what target +you're compiling to, where are your tools, etc. + +Another problem is that compilers come with standard libraries only (like +icompiler-rt, libcxx, libgcc, libm, etc), so you'll have to find and make +available to the build system, every other library required to build your +software, that is specific to your target. It's not enough to have your +host's libraries installed. + +Finally, not all toolchains are the same, and consequently, not every Clang +option will work magically. Some options, like --sysroot (which +effectively changes the logical root for headers and libraries), assume +all your binaries and libraries are in the same directory, which may not +true when your cross-compiler was installed by the distribution's package +management. So, for each specific case, you may use more than one +option, and in most cases, you'll end up setting include paths (-I) and +library paths (-L) manually. + +To sum up, different toolchains can: + * be host/target specific or more flexible + * be in a single directory, or spread out your system + * have different sets of libraries and headers by default + * need special options, which your build system won't be able to figure + out by itself + +General Cross-Compilation Options in Clang +========================================== + +Target Triple +------------- + +The basic option is to define the target architecture. For that, use +``-target ``. If you don't specify the target, CPU names won't +match (since Clang assumes the host triple), and the compilation will +go ahead, creating code for the host platform, which will break later +on when assembling or linking. + +The triple has the general format ``---``, where: + * ``arch`` = x86, arm, thumb, mips, etc. + * ``sub`` = for ex. on ARM: v5, v6m, v7a, v7m, etc. + * ``vendor`` = pc, apple, nvidia, ibm, etc. + * ``sys`` = none, linux, win32, darwin, cuda, etc. + * ``abi`` = eabi, gnu, android, macho, elf, etc. + +The sub-architecture options are available for their own architectures, +of course, so "x86v7a" doesn't make sense. The vendor needs to be +specified only if there's a relevant change, for instance between PC +and Apple. Most of the time it can be omitted (and Unknown) +will be assumed, which sets the defaults for the specified architecture. +The system name is generally the OS (linux, darwin), but could be special +like the bare-metal "none". + +When a parameter is not important, they can be omitted, or you can +choose "unknown" and the defaults will be used. If you choose a parameter +that Clang doesn't know, like "blerg", it'll ignore and assume `Unknown`, +which is not always desired, so be careful. + +Finally, the ABI option is something that will pick default CPU/FPU, +define the specific behaviour of your code (PCS, extensions), +and also choose the correct library calls, etc. + +CPU, FPU, ABI +------------- + +Once your target is specified, it's time to pick the hardware you'll +be compiling to. For every architecture, a default set of CPU/FPU/ABI +will be chosen, so you'll almost always have to change it via flags. + +Typical flags include: + * ``-mcpu=``, like x86-64, swift, cortex-a15 + * ``-fpu=``, like SSE3, NEON, controlling the FP unit available + * ``-mfloat-abi=``, like soft, hard, controlling which registers + to use for floating-point + +The default is normally the common denominator, so that Clang doesn't +generate code that breaks. But that also means you won't get the best +code for your specific hardware, which may mean orders of magnitude +slower than you expect. + +For example, if your target is "arm-none-eabi", the default CPU will +be "arm7tdmi" using soft float, which is extremely slow on modern cores, +whereas if your triple is "armv7a-none-eabi", it'll be Cortex-A8 with +NEON, but still using soft-float, which is much better, but still not +great. + +Toolchain Options +----------------- + +There are four main options to control access to your cross-compiler: +``--sysroot``, ``-I`` and ``-L``. The two last ones are well known, +but they're particularly important for additional libraries +and headers that are specific to your target. + +There are two main ways to have a cross-compiler: + +#. When you have extracted your cross-compiler from a zip file into + a directory, you have to use ``--sysroot=``. The path is the + root directory where you have unpacked your file, and Clang will + look for the directories ``bin``, ``lib``, ``include`` in there. + + In this case, your setup should be pretty much done (if no + additional headers or libraries are needed), as Clang will find + all binaries it needs (assembler, linker, etc) in there. + +#. When you have installed via a package manager (modern Linux + distributions have cross-compiler packages available), make + sure the target triple you set is `also` the prefix of your + cross-compiler toolchain. + + In this case, Clang will find the other binaries (assembler, + linker), but not always where the target headers and libraries + are. People add system-specific clues to Clang often, but as + things change, it's more likely that it won't find than the + other way around. + + So, here, you'll be a lot safer if you specify the include/library + directories manually (via ``-I`` and ``-L``). + +Target-Specific Libraries +========================= + +All libraries that you compile as part of your build will be +cross-compiled to your target, and your build system will probably +find them in the right place. But all dependencies that are +normally checked against (like libxml or libz etc) will match +against the host platform, not the target. + +So, if the build system is not aware that you want to cross-compile +your code, it will get every dependency wrong, and your compilation +will fail during build time, not configure time. + +Also, finding the libraries for your target are not as easy +as for your host machine. There aren't many cross-libraries available +as packages to most OSs, so you'll have to either cross-compile them +from source, or download the package for your target platform, +extract the libraries and headers, put them in specific directories +and add ``-I`` and ``-L`` pointing to them. + +Also, some libraries have different dependencies on different targets, +so configuration tools to find dependencies in the host can get the +list wrong for the target platform. This means that the configuration +of your build can get things wrong when setting their own library +paths, and you'll have to augment it via additional flags (configure, +Make, CMake, etc). + +Multilibs +--------- + +When you want to cross-compile to more than one configuration, for +example hard-float-ARM and soft-float-ARM, you'll have to have multiple +copies of you libraries and (possibly) headers. + +Some Linux distributions have support for Multilib, which handle that +for you in an easier way, but if you're not careful and, for instance, +forget to specify ``-ccc-gcc-name armv7l-linux-gnueabihf-gcc`` (which +uses hard-float), Clang will pick the ``armv7l-linux-gnueabi-ld`` +(which uses soft-float) and linker errors will happen. + +The same is true if you're compiling for different ABIs, like ``gnueabi`` +and ``androideabi``, and might even link and run, but produce run-time +errors, which are much harder to track and fix. + diff --git a/docs/index.rst b/docs/index.rst index 853fcc1ccb..90165d6cfb 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -18,6 +18,7 @@ Using Clang as a Compiler UsersManual LanguageExtensions + CrossCompilation AddressSanitizer ThreadSanitizer MemorySanitizer -- 2.40.0