Cross-compilation using Clang

Introduction

This document will guide you in choosing the right Clang options for cross-compiling 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 “how to” and won’t help you setting your build system or Makefiles, nor choosing the right CMake options, etc. Also, it does not cover all the possible options, nor does it contain specific examples for specific architectures. For a concrete example, the instructions for cross-compiling LLVM itselfmay be of interest.

After reading this document, you should be familiar with the main issues related to cross-compilation, 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 for programmers wishing to compile to different platforms and architectures, and for compiler developers that only have to maintain one build system, and for 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, OS’s 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 your tools are, etc.

Another problem is that compilers come with standard libraries only (like compiler-rtlibcxxlibgcclibm, 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 across 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 <triple>. 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 <arch><sub>-<vendor>-<sys>-<abi>, where:
  • arch = x86armthumbmips, etc.
  • sub = for ex. on ARM: v5v6mv7av7m, etc.
  • vendor = pcapplenvidiaibm, etc.
  • sys = nonelinuxwin32darwincuda, etc.
  • abi = eabignuandroidmachoelf, 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, it 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=<cpu-name>, like x86-64, swift, cortex-a15
  • -mfpu=<fpu-name>, like SSE3, NEON, controlling the FP unit available
  • -mfloat-abi=<fabi>, 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 three 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:

  1. When you have extracted your cross-compiler from a zip file into a directory, you have to use --sysroot=<path>. The path is the root directory where you have unpacked your file, and Clang will look for the directories binlibinclude 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.

  2. When you have installed via a package manager (modern Linux distributions have cross-compiler packages available), make sure the target triple you set is alsothe 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 OS’s, 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 your 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-namearmv7l-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 down and fix.

时间: 2024-10-23 20:04:02

Cross-compilation using Clang的相关文章

cross compile vlc 播放器

上一篇文章介绍了如何交叉编译 FFmpeg ,继续介绍  VLC播放器  交叉编译 . 首先下载 vlc 源码  我用的是 2.2.6  地址 : http://mirrors.neusoft.edu.cn/videolan/vlc/2.2.6/vlc-2.2.6.tar.xz  解压,进入目录. 然后  设置 ffmpeg路径  ,上一章把ffmpeg 装在了   --prefix=/exports/rfs/usr   对应得在 交叉工具 脚本 中添加 export PKG_CONFIG_PA

Qt5.7.0配置选项(configure非常详细的参数)

configure是一个命令行工具,用于配置Qt编译到指定平台.configure必须运行于Qt源码根目录.当运行configure时,编译源码使用的是所选工具链中的make工具. 一.源码目录.编译目录和安装目录 源码目录就是包含源码的目录.编译目录是包含Makefiles文件.object文件和其他中间文件的目录.安装目录是二进制文件和库文件安装的目录. 当编译目录和源码目录不一样时,称为影子编译(shadow build),比如说,Qt Creator默认是使用影子编译来编译工程的.这里也

Build Clover

#!/bin/bash #set -x # made by Micky1979 on 07/05/2016 based on Slice, Zenith432, STLVNUB, JrCs, cvad, Rehabman, and ErmaC works # Tested in OSX using both GNU gcc and clang (Xcode 6.4, 7.2.1, 7.3.1 and Xcode 8). # Preferred OS is El Capitan with Xcod

【转】Ubuntu安装ARM架构GCC工具链(ubuntu install ARM toolchain)最简单办法

原文网址:http://www.cnblogs.com/muyun/p/3370996.html 一.安装ARM-Linux-GCC工具链 只需要一句命令: sudo apt-get install gcc-arm-linux-gnueabi 前提是你的Ubuntu系统版本是官网支持的最新的版本,若不是,请升级.执行以上命令即可. 二.使用工具链 注意!这里不能使用 gcc 命令来召唤它.它的名字是 arm-linux-gnueabi-gcc .如果出现 Command Not Found,请关

使用sh-x调试shell脚本

参考:http://blog.chinaunix.net/uid-20564848-id-73502.html 1. 通过sh -x 脚本名  #显示脚本执行过程2.脚本里set -x选项,轻松跟踪调试shell脚本 [以下字段转自:http://linux.chinaitlab.com/SHELL/727128_4.html]"-x"选项可用来跟踪脚本的执行,是调试shell脚本的强有力工具."-x"选项使shell在执行脚本的过程中把它实际执行的每一个命令行显示

交叉编译概述

交叉编译,简单地说,就是在 一个平台上生成另一个平台上的可执行代 . 要进行交叉编译,我们需要在主机平台上安装对应的交叉编译工具链(cross compilation tool chain),然后用这个交叉编译工具链编译我们的源代码,最终生成可在目标平台上运行的代码.常见的交叉编译例子如下: 1.在Windows PC上,利用ADS(ARM 开发环境),使用armcc编译器,则可编译出针对ARM CPU的可执行代码. 2.在Linux PC上,利用arm-linux-gcc编译器,可编译出针对L

QT嵌入式平台配置

Qt5 on ARM platforms - IntroductionQt5 ARM 平台移植#################################################### Introduction: This short post covers the background of Qt5, architec tural details, configuring for eglfs with Graphics drivers, building, and known i

朱恒志20135314实验1 实验报告

北京电子科技学院(BESTI) 实     验    报     告 课程:密码系统设计基础                  班级:53 姓名:朱恒志 学号:20135314 成绩:             指导教师:娄嘉鹏      实验日期:2015.11.10 实验密级:         预习程度:           实验时间:15:30~17:30 仪器组次:1         必修/选修:必修       实验序号:14 实验名称:    信息安全系统设计基础实验一 实验目的与要求

Ubuntu Qt 交叉编译(树莓派2b)

在一个平台上生成另一个平台上的可执行代码.为什么要大费周折的进行交叉编译呢?一句话:不得已而为之.有时是因为目的平台上不允许或不能够安装所需要的编译器,而又需要这个编译器的某些特征:有时是因为目的平台上的资源贫乏,无法运行所需要的编译器:有时又是因为目的平台还没有建立,连操作系统都没有,根本谈不上运行什么编译器. 要进行交叉编译,我们需要在主机平台上安装对应的交叉编译工具链(cross compilation tool chain),然后用这个交叉编译工具链编译源代码,最终生成可在目标平台上运行