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-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 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
=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, 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:
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 directoriesbin
,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 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.
Cross-compilation using Clang的更多相关文章
- golang 跨平台编译——go 在windows上编译Linux平台的程序(Cross Compilation from Windows to Linux/Ubuntu)
Go Cross Compilation from Windows to Linux/Ubuntu I have GO 1.7 installed on my Windows 10. I create ...
- [转]在 Mac OS X上编译 libimobiledevice 的方法
link: http://blog.boceto.fr/2012/05/05/libimobiledevice-for-macosx/ The objective of the day: Compil ...
- RPi Kernel Compilation
Overview This page explains how to rebuild the kernel image for the RPi. There are two possible rout ...
- aarch64 cross compile 交叉编译 opencv
需求 : linux host : UBUNTU opencv source : opencv 3.3.1.zip CMAKE : apt-get install cmake cmake-qt- ...
- cross compile vlc 播放器
上一篇文章介绍了如何交叉编译 FFmpeg ,继续介绍 VLC播放器 交叉编译 . 首先下载 vlc 源码 我用的是 2.2.6 地址 : http://mirrors.neusoft.edu ...
- Qt5.7.0配置选项(configure非常详细的参数)
configure是一个命令行工具,用于配置Qt编译到指定平台.configure必须运行于Qt源码根目录.当运行configure时,编译源码使用的是所选工具链中的make工具. 一.源码目录.编译 ...
- x265编译
x265 HEVC Encoder Mission Statement Online documentation Mailing list x265-devel@videolan.org HOWTO ...
- xmake v2.3.4 发布, 更加完善的工具链支持
为了让xmake更好得支持交叉编译,这个版本我重构了整个工具链,使得工具链的切换更加的方便快捷,并且现在用户可以很方便地在xmake.lua中扩展自己的工具链. 关于平台的支持上,我们新增了对*BSD ...
- xmake v2.3.7 发布, 新增 tinyc 和 emscripten 工具链支持
xmake 是一个基于 Lua 的轻量级跨平台构建工具,使用 xmake.lua 维护项目构建,相比 makefile/CMakeLists.txt,配置语法更加简洁直观,对新手非常友好,短时间内就能 ...
随机推荐
- R语言绘图时的边界碰撞问题
当我们在绘图时,经常会遇到这样的问题,添加的文字标记超出了坐标系的问题,导致文字显示不全 比如下面这个例子: plot(c(1,5),c(1,5)) text(5,5.1,"ABCDEF&q ...
- 由于PADT伪造攻击带来的大面积掉线原因分析
今天一早接到一个客户电话,说他有一个交换机下面的用户,大面积和上线下线. 由于之有已建议用户在主干换了普通VLAN交换机.所以这次出现问题概率较小,只在一条支路的交换机下面. 下面我对这个情况的发生做 ...
- 7.1 安装软件包的三种方法 7.2 rpm包介绍 7.3 rpm工具用法 7.4 yum工具用法 7.5 yum搭建本地仓库
7.1 安装软件包的三种方法 7.2 rpm包介绍 7.3 rpm工具用法 7.4 yum工具用法 7.5 yum搭建本地仓库 三种方法 rpm工具----->类型windows下的exe程序 ...
- spring 配置 Java配置类装配bean
https://www.cnblogs.com/chenbenbuyi/p/8457700.html 自动化装配的确有很大的便利性,但是却并不能适用在所有的应用场景,比如需要装配的组件类不是由自己的应 ...
- vue父组件向子组件动态传值的两种方法
在一些项目需求中需要父组件向子组件动态传值,比如我这里的需求是,父组件动态通过axios获取返回的图片url数组然后传给子组件,上传图片的子组件拿到该数组后进行遍历并展示图片,因为有时候获取到的会是空 ...
- SQLServer查看存储过程的方法
使用 sp_helptext 查看存储过程的定义 在对象资源管理器中,连接到 数据库引擎实例,再展开该实例. 在工具栏上,单击“新建查询”. 在查询窗口中,输入下列语句.更改数据库名称和存储过程名称以 ...
- WebGL 进入三维世界
1.观察目标点和上方向 为了确定观察者的状态,你需要获取两项信息:视点,即观察者的位置:观察目标点(look-at point),即被观察目标所在的点,它可以用来确定视线.此外,因为我们需要把观察到的 ...
- springMVC中如何访问WebContent中的资源文件
一.问题: 我的工程目录如下: WebContent |-css |-js |-imgs |-META-INF |-WEB-INF |-jsp |-login.jsp 如何在login.jsp中引用i ...
- mysql 连接字符串 CONCAT
以前用SQL Server 连接字符串是用“+”,现在数据库用mysql,写个累加两个字段值SQL语句居然不支持"+",郁闷了半天在网上查下,才知道mysql里的+是数字相加的操作 ...
- HTML5 标准规范完成了
万维网联盟(W3C)昨天宣布,HTML5 标准规范终于最终制定完成了,并已公开发布.对于前端工程师来说,这无疑是一个振奋人心的好消息. 众所周知,HTML5改变了互联网,将成为 ...