Cmake使用教程交叉编译

Cmake Cross Compile UserGuide

1. 设置系统和工具链

对于交叉编译,CMake并不知道目标系统是什么,所以需要设置一些CMake变量来告知CMake,

  • CMAKE_SYSTEM_NAME:即目标系统名,这里是Linux
  • CMAKE_SYSTEM_PROCESSOR :目标系统的处理器名,这里是arm

对于工具链,则是通过下面2个变量来定位,

  • CMAKE_C_COMPILER:C编译器的可执行文件名称
  • CMAKE_CXX_COMPILER:C++编译器的可执行文件名称

这些变量可以在调用CMake时通过命令行传递,但是这种做法容易出错,而且用起来不方便,所以CMake提供了工具链文件的方式来传递这些变量信息。

2. 工具链文件

我们在工程里新建一个文件叫arm_linux_setup.cmake,放置位置如下(也可以放在别的地方),

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)

set(tools /home/wh/work/cross_compile/gcc-linaro-7.3.1-2018.05-x86_64_arm-linux-gnueabihf)
set(CMAKE_C_COMPILER ${tools}/bin/arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER ${tools}/bin/arm-linux-gnueabihf-g++)

注意:

  • 上述命令必须写入脚本中,使用 -DCMAKE_TOOLCHAIN_FILE=xxx.cmake 的方式使用。不能直接写入 CMakeLists.txt 或使用 include(xx.cmake) 。
  • set(CMAKE_SYSTEM_NAME Linux):该指令必须存在,其目的是设置目标机使用的操作系统名称,支持Linux,QNX,WindowsCE,Android等。如果没有操作系统,那么就写 Generic。执行该指令后,cmake 变量CMAKE_CROSSCOMPILING 会自动被设置为 TRUE,此时 cmake 就会“知道“现在执行的是交叉编译;

tools是本人使用的交叉工具链路径,可以根据自己的实际文件来做修改。

3. 编译

使用CMake的变量CMAKE_TOOLCHAIN_FILE来指定工具链文件,cd到build目录,然后执行下面的命令,

# 注意,工具链文件的指定一定要紧跟cmake命令之后,不能放到 .. 后面
cmake -DCMAKE_TOOLCHAIN_FILE=../arm_linux_setup.cmake -DCMAKE_INSTALL_PREFIX=/XXX/XXX ..

使用make开始安装编译源代码

make  # 编译源代码
make DESTDIR=/install/directory install # 配置安装路径为指定路径

使用file命令去查看这个文件,可以看到其运行平台是32位ARM处理器上的Linux系统,

file executable

使用工具链文件的好处就是只要编写一遍,然后在任意地方只需要使用CMAKE_TOOLCHAIN_FILE去指定其位置就可以了,非常方便。

4. 其他说明

     通常,我们在开发时,需要使用系统库或第三方库的功能,在生成可执行文件时,将其进行链接。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 个变量,它们的值为 NEVER 、 ONLY 或 BOTH:

     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_PROGRAM 为 NEVER,set(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。

Reference

cmake:交叉编译
Cmake Cross Compile Office Doc
CrossCompile for Raspiberry
CMake交叉编译Arm Linux程序

转载请注明出处!感谢GISPALAB实验室的老师和同学们的帮助和支持~
原文地址:https://www.cnblogs.com/uestc-mm/p/15666249.html