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程序