一、背景
本文针对在x86平台(ubuntu系统)如何交叉编译提出思路和解决方案。具有实践性。
二、思路
目的:在x86上用 docker 方式交叉编译 arm 平台程序。
有时项目庞大,依赖库之多,以至于用新标准,或 boost 库,不一而足。使用容器方式,既可保证版本环境一致,又可保持宿主机系统之纯净,还可重用编译环境之镜像,一举多得,可谓编译界之大器,不得不学。
三、如何运行 arm 版本容器
x86 无法运行 arm 平台程序,然 qemu 提供用户级别之机制,通过 qemu-arm-static 可以达到目的。在 ubuntu 上安装:
1 | sudo apt install qemu-user-static |
另一种方法,可以借助 qemu-user-static 镜像,此情况下无须手动拷贝 qemu-arm-static。示例:
1 | # docker run --rm --privileged multiarch/qemu-user-static --reset -p yes |
注:https://github.com/multiarch 还有许多跨平台的项目。
此步解决了如何运行容器的问题。
四、交叉编译
下面列出2种方式。第1种方式控制编译操作进程。第2种方便一键操作(当然,国内网络环境非常难达到一键之目的)。
4.2 编译方式:容器内
概述如下:下载arm版本的基础镜像,使用上节方式运行容器,再在其中进行编译,至于源码及压缩包,使用docker cp
命令即可。
1 | # 64位的: |
进入容器后用 getconf LONG_BIT 可确诊系统位数。在此容器中安装gcc、make等均为arm版本,此时无须再指定 CROSS_COMPILE 变量。
安装了交叉编译环境后的镜像可保存备用,如上传到 dockerhub 上。
4.3 编译方式:容器外
概述如下:编写 Dockerfile 文件,基于arm版本的基础镜像,其它如apt-get install
无须修改。
创建文件 Dockerfile.arm,以示区别。内容概述:
1 | ARG BUILD_FROM=arm64v8 |
注意,此处为了兼容不同版本的arm,因而使用了参数。
首先运行 qemu-user-static 镜像,否则无须执行 arm 版本的构建:
1 | docker run --rm --privileged multiarch/qemu-user-static --reset -p yes |
--build-arg
表示指定构建镜像时的参数,须与 Dockerfile保持一致。
五、未完事宜
在容器中编译、运行问题。即把编译、运行分别,而不是放到一个容器。
本文所述,与 Docker 版本有关,最低为何种,有说 17.05,但未研究。另外,对内核版本也有要求,测试4.4版本无法使用,4.8版本支持。因此,建议使用较新版本。
六 笔记
此节为笔记,可忽略。
进入了 arm 版本的容器,绝大部分的操作与 x86 ubuntu 完全一致。非常方便。
arm64 版本更新时提示信息:
1 | Get:6 http://ports.ubuntu.com/ubuntu-ports xenial/universe arm64 Packages [9493 kB] |
arm32版本如下:
1 | Get:3 http://ports.ubuntu.com/ubuntu-ports xenial-backports InRelease [107 kB] |
编译 boost 库示例。arm64 版本:
1 | ./bootstrap.sh && ./b2 install |
原因:未检测到arm平台。其检测代码在$BOOST_DIR/libs/config/checks/architecture/arm.cpp
文件:
1 | #if !defined(__arm__) && !defined(__thumb__) && \ |
添加 arm 64 的支持:!defined(__aarch64__)
:
1 | #if !defined(__arm__) && !defined(__thumb__) && \ |
修改后,上述 arm 项变成 yes,因为是运行时检测的。
实际上,可以通过参数 architecture 指定平台。
1 | ./bootstrap.sh && ./b2 architecture=arm install |
此时,当然无法检测,但实际上是 arm 平台。
arm32 版本:
1 | ./b2 install |
因为在 arm.cpp 中默认有 arm 的宏定义,故检测通过。
编译速度依赖于机器性能,在阿里云单核 2GB 主机上交叉编译一套不具名的开源项目,加上涉及 boost 库和 c++14 标准,从 2月25日13点开始,至2月26日17时,耗时约28小时。