cmake 指定 c++ 编译器_cmake:交叉编译

294c21fe653403a47bdddca5c5e2e2c1.png

概念

我们在 PC 上进行开发时,需要使用编译器和链接器生成能够在我们机器上运行的可执行程序。但是当涉及到嵌入式开发时,情况就不同了。因为嵌入式设备的资源(CPU、RAM等)无法和 PC 相比,在设备上构建编译系统很麻烦或者根本不可能构建。因此通常做法是在 PC 上使用交叉编译工具链生成能够在嵌入式设备运行的可执行程序,然后再将程序放到设备中去执行。

此为交叉编译。一般称 PC 为 主机,嵌入式设备为目标机

编写脚本

使用 cmake 进行交叉编译,只需几条命令即可。

set(CMAKE_SYSTEM_NAME Linux)
​
set(TOOLCHAIN_PATH /OPT/gcc-arm-linux-gnueabi)
set(CMAKE_C_COMPILER ${tools}/bin/arm-linux-gnueabi-gcc)
set(CMAKE_CXX_COMPILER ${tools}/bin/arm-linux-gnueabi-g++)

set(CMAKE_SYSTEM_NAME Linux)该指令必须存在,其目的是设置目标机使用的操作系统名称,支持LinuxQNXWindowsCEAndroid等。如果没有操作系统,那么就写 Generic。执行该指令后,cmake 变量——CMAKE_CROSSCOMPILING 会自动被设置为 TRUE,此时 cmake 就会“知道“现在执行的是交叉编译;

由于 cmake 无法自动获取目标机器信息,因此需要显式指明编译工具。

CMAKE_C_COMPILER:设置 C 编译器;

CMAKE_CXX_COMPILER:设置 c++ 编译器

使用方式

  1. 将上述 4 条指令保存在 xxx.cmake 文件中,比如 CrossCompile.cmake
  2. 使用 cmake -DCMAKE_TOOLCHAIN_FILE= path/CrossCompile.cmake src-path 构建编译系统;
  3. 执行 make 指令;

注意:上述命令必须写入脚本中,使用 -DCMAKE_TOOLCHAIN_FILE=xxx.cmake 的方式使用。不能直接写入 CMakeLists.txt 或使用 include(xx.cmake)

测试例程

目录结构:

sdc@ubuntu:~/cross-compile$ tree .
.
├── build
├── CMakeLists.txt
├── CrossCompile.cmake
└── main.c
​
1 directory, 3 files

结果:

b814aae871cb114f1d595437638d8dd7.png

其他说明

通常,我们在开发时,需要使用系统库或第三方库的功能,在生成可执行文件时,将其进行链接。cmake 提供了 FIND_PROGRAM()FIND_LIBRARY()FIND_FILE()FIND_PATH()FIND_PACKAGE() 实现相应的查找功能。如果我们在进行交叉编译时使用了上述指令,那么并不能生成可执行文件。因为默认情况下,上述指令查找的是主机上的相关文件,其并不适用于目标机器。还好,cmake 为我们提供了相应的变量:

CMAKE_FIND_ROOT_PATH:设置其值为一系列的目录(set(CMAKE_FIND_ROOT_PATH path1 path2 path3 ...),这样在执行 FIND_XXX() 指令时就会从这一系列的目录中进行查找。

跟随该变量的有下述 3 个变量,它们的值为 NEVERONLYBOTH

CMAKE_FIND_ROOT_PATH_MODE_PROGRAM:如果设置为 NEVER,那么 CMAKE_FIND_ROOT_PATH 就不会对 FIND_PROGRAM() 产生影响, FIND_PROGRAM() 不会在 CMAKE_FIND_ROOT_PATH 指定的目录中寻找;如果设置为 ONLY,那么 FIND_PROGRAM() 只会从CMAKE_FIND_ROOT_PATH 指定的目录中寻找;如果设置为 BOTH,那么 FIND_PROGRAM() 会优先从 CMAKE_FIND_ROOT_PATH 指定的目录中寻找,再从默认的目录中寻找。

因为 FIND_PROGRAM() 大部分情况下用于寻找可执行程序,给后续的 EXECUTE_PROCESS()ADD_CUSTOM_COMMAND() 指令使用。并且,只有主机在生成编译文件时使用该可执行程序。因此通常设置 CMAKE_FIND_ROOT_PATH_MODE_PROGRAMNEVERset(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)

CMAKE_FIND_ROOT_PATH_MODE_LIBRARY:由于在进行交叉编译,所以只能使用 FIND_LIBRARY() 查找符合目标机器的库文件,因此设置该变量值为ONLY(set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)),表示只从 CMAKE_FIND_ROOT_PATH 指定的目录中查找;

CMAKE_FIND_ROOT_PATH_MODE_INCLUDE:同上,将其值设置为 ONLY

参考(请仔细阅读)

https://gitlab.kitware.com/cmake/community/wikis/doc/cmake/CrossCompiling

https://blog.kitware.com/cross-compiling-for-raspberry-pi/

  • 5
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值