CMake 交叉编译实践:国产CPU,支持 aarch64、loongarch64 和 mips64 架构

2025-01-05

CMake 交叉编译实践

背景

在当今科技飞速发展的时代,国产芯片的崛起备受瞩目。随着不同架构的国产芯片相继涌现,如支持 aarch64 的鲲鹏芯片、适配 loongarch64 的龙芯芯片以及采用 mips64 架构的部分芯片等,如何让软件能够在这些多样的芯片环境下顺畅运行成为了关键课题。

为什么要交叉编译

  • 开发便利性与效率提升

在开发过程中,使用熟悉的主机操作系统(如常见的 Windows、Linux 桌面发行版)进行代码编写、调试和编译,相比于直接在陌生且资源受限的目标芯片操作系统环境下操作,便利性大幅提升。开发者可以便捷地使用各种丰富的开发工具、集成开发环境(IDE),快速定位和修复代码问题,加速开发迭代周期。一旦代码在主机上通过交叉编译验证无误,再部署到目标芯片上进行最终测试,能极大提高整体开发效率。

  • 多平台适配需求

随着国产芯片架构的多样化发展,一款软件常常需要适配多种不同架构的芯片,以满足不同应用场景需求。交叉编译技术使得开发者能够在单一主机平台上,针对不同目标架构轻松切换编译配置,快速生成适配不同芯片的软件版本,避免为每个目标平台单独搭建复杂的本地编译环境,实现一套代码多平台复用,降低开发成本与维护难度。

交叉编译原理

交叉编译,简单来说,就是在一个平台(通常称为主机平台,如常见的 x86 架构 PC)上编译生成可在另一个不同的架构平台(目标平台,如上述的国产芯片架构)上运行的代码。这背后的核心原理在于编译器的 “魔法”。编译器本身是一个将高级编程语言转换为机器可识别二进制指令的工具,在交叉编译场景下,它能够模拟目标平台的指令集、系统调用等关键特性。

交叉编译工具链

交叉编译工具链,也叫交叉编译器,是专门为交叉编译而设的工具链,它提供了编译器、链接器、库等工具,用于在主机平台上编译生成目标平台的可执行文件。

实操指南

  1. 克隆cmake工程

本项目整合了多种架构的工具链,并提供了自动化构建脚本。你可以从以下地址克隆工程:

GitHub: cmake_template

  1. 交叉编译工具链下载

对于 Linux 系统,可以通过包管理器安装或下载预编译好的工具链。以下是各架构推荐的工具链版本及其安装命令:

AArch64 架构

使用 Linaro 提供的 GCC 5.4 版本:

1
2
wget https://releases.linaro.org/components/toolchain/binaries/5.4-2017.05/aarch64-linux-gnu/gcc-linaro-5.4.1-2017.05-x86_64_aarch64-linux-gnu.tar.xz
tar -xf gcc-linaro-5.4.1-2017.05-x86_64_aarch64-linux-gnu.tar.xz -C /opt/

LoongArch64 架构

使用龙芯提供的工具链:

1
2
3
wget https://github.com/loongson/build-tools/releases/download/2024.11.01/x86_64-cross-tools-loongarch64-binutils_2.43.1-gcc_14.2.0-glibc_2.40.tar.xz
tar -xf x86_64-cross-tools-loongarch64-binutils_2.43.1-gcc_14.2.0-glibc_2.40.tar.xz -C /opt/
mv /opt/cross-tools/ /opt/x86_64-cross-tools-loongarch64-binutils_2.43.1-gcc_14.2.0-glibc_2.40/

MIPS64 架构

同样来自龙芯的工具链:

1
2
wget http://ftp.loongnix.cn/toolchain/gcc/release/mips/gcc7/mips-loongson-gcc7.3-2019.06-29-linux-gnu.tar.gz
tar -xf mips-loongson-gcc7.3-2019.06-29-linux-gnu.tar.gz -C /opt/
  1. 配置环境变量

在交叉编译过程中,需要配置一些环境变量来告诉 CMake 使用正确的工具链和目标平台信息。以下是详细的配置说明:

  • CMAKE_SYSTEM_NAME:指定目标系统的名称。这里设置为 Linux,表示目标系统是 Linux。
  • CMAKE_SYSTEM_PROCESSOR:指定目标系统的处理器架构。这里设置为 aarch64,表示目标处理器架构是 aarch64。对于其他架构,可以相应地设置为 loongarch64 或 mips64。
  • CMAKE_SYSROOT:指定目标系统的根目录。这个目录包含了目标系统的头文件、库文件等。这里使用环境变量 $ENV{CROSS_COMPILE_SYSROOT} 来指定。
  • CMAKE_C_COMPILER:指定 C 编译器的路径。这里使用环境变量 $ENV{CROSS_COMPILE_ROOT} 和 $ENV{CROSS_COMPILE} 来构建完整的路径,例如 /opt/gcc-linaro-5.4.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc。
  • CMAKE_CXX_COMPILER:指定 C++ 编译器的路径。类似地,使用环境变量 $ENV{CROSS_COMPILE_ROOT} 和 $ENV{CROSS_COMPILE} 来构建完整的路径,例如 /opt/gcc-linaro-5.4.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-g++。
  • CMAKE_CXX_FLAGS_DEBUG:指定 C++ 编译器在调试模式下的编译选项。这里添加了 -O0 -Wall -ggdb,表示不进行优化、启用所有警告信息并生成调试信息。

配置环境变量的示例:

1
2
3
4
5
6
SET(CMAKE_SYSTEM_NAME              Linux)
SET(CMAKE_SYSTEM_PROCESSOR aarch64)
SET(CMAKE_SYSROOT $ENV{CROSS_COMPILE_SYSROOT})
SET(CMAKE_C_COMPILER $ENV{CROSS_COMPILE_ROOT}/bin/$ENV{CROSS_COMPILE}gcc)
SET(CMAKE_CXX_COMPILER $ENV{CROSS_COMPILE_ROOT}/bin/$ENV{CROSS_COMPILE}g++)
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -Wall -ggdb")

所有架构的工具链配置均已完成,详情参见 toolchains 文件夹。

https://github.com/jaywongX/cmake_template/tree/main/toolchains

  1. 编译过程

每个架构都有对应的构建脚本,执行如下命令即可开始编译:

  • 编译aarch64
1
/bin/bash build-aarch64.sh
  • 编译loongarch64
1
/bin/bash build-loongarch64.sh
  • 编译mips64
1
/bin/bash build-mips64.sh

效果如图:



  1. 测试结果

编译完成后,可以通过检查生成的二进制文件来验证编译是否成功。例如:

  • 测试aarch64
1
2
file built/linux/aarch64/Release/bin/exe-1.0.0.0 
file built/linux/aarch64/Release/lib/libshared_lib.so.1.0.0.0
  • 测试loongarch64
1
2
readelf -h built/linux/loongarch64/Release/bin/exe-1.0.0.0 | grep Machine 
readelf -h built/linux/loongarch64/Release/lib/libshared_lib.so.1.0.0.0| grep Machine
  • 测试mips64
1
2
file built/linux/mips64/Release/bin/exe-1.0.0.0 
file built/linux/mips64/Release/lib/libshared_lib.so.1.0.0.0

效果如图:


0x102 是分配给 LoongArch 架构的 ELF 机器类型代码。