Linux Cmake如何进行交叉编译
发布时间:2025-09-07 00:19       
下面给出一套可直接复用的 CMake 交叉编译方法论与示例,覆盖工具链文件、sysroot、依赖发现、try_compile/try_run
、pkg-config 与打包安装等关键点。🛠️
一、核心思路(一句话)
在主机上用目标架构的编译器和头库(sysroot)进行配置阶段的“假执行+真编译”,禁止在配置期跑目标程序,并把依赖搜索限定到目标 sysroot。✅
二、准备清单
- 交叉编译器:如
aarch64-linux-gnu-gcc/g++
或arm-linux-gnueabihf-gcc/g++
- 目标 rootfs/sysroot:
/opt/sysroots/aarch64
(含include/
与lib/
) - CMake ≥ 3.16(建议 3.22+,Preset 更好用)
- 可选:
qemu-<arch>
(仅在需要运行目标程序做测试时)
三、最小可用 Toolchain 文件(推荐保存为 toolchain-aarch64.cmake
)
# 目标系统与架构
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)
# 指定交叉编译器(全路径或通过 PATH)
set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++)
# 指定 sysroot(头文件与库的根)
set(CMAKE_SYSROOT /opt/sysroots/aarch64)
# 依赖搜索只在 sysroot 内进行
set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # 程序走主机 PATH
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) # 库只在 sysroot
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) # 头文件只在 sysroot
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) # 包只在 sysroot
# 配置期不运行目标二进制,避免“可执行文件格式错误”
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
# pkg-config 指向目标库(如有)
set(ENV{PKG_CONFIG_SYSROOT_DIR} ${CMAKE_SYSROOT})
set(ENV{PKG_CONFIG_LIBDIR} ${CMAKE_SYSROOT}/usr/lib/pkgconfig:${CMAKE_SYSROOT}/usr/share/pkgconfig)
要点解释:
CMAKE_SYSTEM_NAME/PROCESSOR
告诉 CMake “这是交叉编译”。CMAKE_SYSROOT
+CMAKE_FIND_ROOT_PATH_MODE_*
将库/头查找限定到目标环境。CMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY
禁掉配置期执行。🚫
四、标准命令行
cmake -S . -B build-aarch64 \
-DCMAKE_TOOLCHAIN_FILE=toolchain-aarch64.cmake \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr \
-DCMAKE_STAGING_PREFIX=/tmp/stage-aarch64
-S/-B
:源码与构建目录分离。CMAKE_INSTALL_PREFIX
:目标系统内的安装前缀(如/usr
)。CMAKE_STAGING_PREFIX
:将安装产物“假装”安装到打包目录,便于后续打包或拷入 rootfs。📦
随后编译与“打包安装”:
cmake --build build-aarch64 -j
cmake --install build-aarch64
五、依赖与 pkg-config 的正确打开方式
- 目标库(如 OpenSSL、zlib、protobuf)需在目标架构下预装到
${CMAKE_SYSROOT}
。 - 若用
find_package(OpenSSL REQUIRED)
,确保对应的*.cmake
或pkgconfig
位于 sysroot。 - 通过上面的
PKG_CONFIG_*
环境变量,find_package(PkgConfig)
+pkg_check_modules()
才会命中目标版本。🔍
六、Clang/多目标的补充(可选)
若用 Clang + LLVM:
set(CMAKE_C_COMPILER clang)
set(CMAKE_CXX_COMPILER clang++)
set(CMAKE_C_COMPILER_TARGET aarch64-linux-gnu)
set(CMAKE_CXX_COMPILER_TARGET aarch64-linux-gnu)
这样可不依赖特定前缀编译器,只要有对应目标的运行时与 sysroot 即可。🚀
七、try_run
与单元测试
- CMake/部分包在配置期会
try_run
。交叉场景中应避免,或配置CMAKE_CROSSCOMPILING_EMULATOR=qemu-aarch64
以在主机上模拟运行:set(CMAKE_CROSSCOMPILING_EMULATOR qemu-aarch64)
- 更稳妥:在 CI 的目标机/容器里跑测试,构建阶段仅编译与安装。⚠️
八、常见问题速解
- 链接不到目标库:检查
CMAKE_SYSROOT
是否正确;确认lib
目录是否是aarch64
版本;file libxxx.so
核对架构。 - 找不到包:为 sysroot 补齐
xxx-config.cmake
或pkgconfig/*.pc
;必要时用-D<Package>_ROOT=${CMAKE_SYSROOT}/usr
。 - 混入主机库:务必使用
ONLY
策略;不要把主机/usr/lib
加入额外搜索路径。 - C++ ABI 不匹配:目标和交叉工具链的 libstdc++ 版本需匹配;尽量同源(如同套件版本的 GCC)。
九、进阶:CMakePresets.json(团队复用更优雅)
{
"version": 5,
"configurePresets": [
{
"name": "aarch64-release",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build-aarch64",
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "toolchain-aarch64.cmake",
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_INSTALL_PREFIX": "/usr",
"CMAKE_STAGING_PREFIX": "/tmp/stage-aarch64"
}
}
]
}
团队只需 cmake --preset aarch64-release
即可复现同配置。🙌
十、简明清单(拿去就能跑)
- 准备交叉编译器与 sysroot
- 写好
toolchain.cmake
(含SYSROOT
、ONLY
策略、TRY_COMPILE
静态) cmake -S -B -D CMAKE_TOOLCHAIN_FILE=...
配置--build
编译,--install
安装到 staging- 用
file
/readelf
核对产物架构;将/tmp/stage-<arch>
同步到镜像或打包
以上流程覆盖了当下主流 CMake 版本的最佳实践,能稳定落地于 ARM/aarch64/RISC-V 等多架构交叉编译场景。✅✨