概念

交叉编译的简介可以交叉编译详解 一 概念篇Introduction to cross-compiling for Linux

简单理解为:

在当前编译平台下,编译出来的程序能运行在体系结构不同的另一种目标平台上,但是编译平台本身却不能运行该程序。比如,我们在 x86 平台上,编写程序并编译成能运行在 ARM 平台的程序,编译得到的程序在 x86 平台上是不能运行的,必须放到 ARM 平台上才能运行。

当前手头有个项目,目标平台是 aarch64 的嵌入式平台,但开发工作是在 x86_64 架构下的 Windows 或者 Ubuntu 系统上进行的, 如果每次开发完,都去嵌入式平台上编译,不仅耗时费力,很多时候嵌入式平台的内存都要爆掉。因此,搭建一个交叉编译环境,在开发平台上编译,在目标平台上运行,显得尤为重要。

环境搭建

在参考了 Ubuntu安装arm-linux-gcc交叉编译器 后,了解到,在 ubuntu 上,既可以使用包管理的方式安装交叉编译器,也可以手动安装较新版本的。arm-linux-gcc 的交叉编译器 7.5 以前的版本由 linaro 维护,可以在 https://releases.linaro.org/components/toolchain/gcc-linaro/ 处下载;7.5 之后的版本可以在 arm 观望中获取:GNU-A Downloads

下载的时候注意查看目标平台的 glibc 版本和 gcc 版本,可通过 ldd --versiongcc --version 查看,最好保证目标平台的版本兼容你下载的交叉编译工具链的版本(高版本兼容低版本,反之不行)。

本文下载的是 x86_64 Linux hosted cross compilers 下面的 gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu.tar.xz 版本。

下载完后,做了如下操作:

1
2
tar -xvf gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu.tar.x
sudo mv gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu /usr/local/aarch64

然后将 /usr/local/aarch64/bin/usr/local/aarch64/lib 分别添加到环境变量的 $PATH$LD_LIBRARY_PATH 中。

新开一个终端,输入 aarch64-none-linux-gnu-gcc -v 有相应输出则说明交叉编译器已经配置好了。

编译测试

新建一个 hello.cpp 文件

1
2
3
4
5
6
7
8
#pragma once
#include <iostream>

int main()
{
std::cout << "hello, world" << std::endl;
return 1;
}

使用交叉编译器编译 aarch64-none-linux-gnu-g++ hello.cpp -o hello,将生成的可执行文件上传到目标平台并运行,若成功打印 hello, world 则表示交叉编译成功。

CMake 中指定交叉编译器

手头项目是由 CMake 构建的,在里面指定交叉编译器采用如下方式:

新建一个 aarch64-toolchain.cmake 文件,内容为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#---------------- 交叉编译环境设置 ----------------#
# 编译器设置
set(CMAKE_C_COMPILER "/usr/local/aarch64/bin/aarch64-none-linux-gnu-gcc")
set(CMAKE_CXX_COMPILER "/usr/local/aarch64/bin/aarch64-none-linux-gnu-c++")
# 链接器设置
set(CMAKE_LINKER "/usr/local/aarch64/bin/aarch64-none-linux-gnu-ld")
# 目标系统类型
set(CMAKE_SYSTEM_NAME Linux)
# 目标系统架构
set(CMAKE_SYSTEM_PROCESSOR aarch64)
# 只使用目标系统的库,头文件和包
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

在项目的 CMakeLists.txt 中将其引入:

1
set(CMAKE_TOOLCHAIN_FILE "cmake/aarch64-toolchain.cmake")

—未完待续