首页 > 技术文章 > 10.05-CMake 交叉编译

lizhensheng 2019-07-01 22:29 原文

CMake进行高端开发

前言

参考

Mastering CMake

学习记录

概述

  • 交叉编译,就是软件在一个系统上架构,而在另外系统上运行。
  • 交叉编译意味着
    • CMake不能自动监测目标构件平台(通过toolchain file来显式定义)
    • 在默认的目录下不能找到库和头文件(CMakeLists.txt需要修改来适应多平台)
    • 构建出的可执行文件不能在开发主机上编译(需要虚拟机,兼容层(wine)或者模拟程序)

工具链文件

  • 构造一个文件,然后指定它
  • cmake -DCMAKE_TOOLCHAIN_FILE=~/TC-mingw.cmake ..
  • 这个环境变量只需要指定一次,就会存在CMake cache中,你不用特意编写工具链文件,因为都已经有了。

设定系统

CMAKE_SYSTEM_NAME
CMAKE_SYSTEM_VERSION
CMAKE_SYSTEM_PROCESSOR

设定编译选项

CMAKE_C_COMPILER
CMAKE_CXX_COMPILER

寻找库,软件和其他文件

  • 当交叉编译时,find_file(),find_path()等行为会变得较为复杂。你找到的可能是主机上的库文件,而不是目标平台上的。工具链文件会定义目标平台上的库和头文件,会给出惯例下这些文件的安装目录,而且最好指定一些目录,以免软件弄混。
CMAKE_FIND_ROOT_PATH
# find_library()会寻找的目录
CMAKE_FIND_ROOT_PATH_MODE_PROGRAM
# NERVER, ONLY(只有显式要求搜索时才会执行搜索), BOTH(default). 定义find_program()的行为 ,find_program()一般用来寻找可执行文件,由于可执行文件一般在主机上,所以该变量一般设为NEVER
CMAKE_FIND_ROOT_PATH_MODE_LIBRARY
# for find_library()一般为ONLY
CMAKE_FIND_ROOT_PATH_MODE_INCLUDE
# for find_path and find_file,一般为ONLY

系统探察

  • 软件需要针对目标平台的实际情况进行不同的构建,所以需要对目标系统进行检查
  • 最简单的方法就是检查环境变量,并将这些变量与工具链文件中的变量进行比较

编译检查

  • 有一些宏,如CHECK_INCLUDE_FILES和CHECK_C_SOURCE_RUNS来监测目标平台的相关属性。这些宏内部则会使用try_compile或try_run等命令,会编译一小段代码,通过一些结果来判断一些情况。
try_run(SHARED_LIBRARY_PATH_TYPE # 存放结果的变量,如xxx-FAILED_TO_RUN
SHARED_LIBRARY_PATH_INFO_COMPILED # 存放结果的变量,TRUE 或 FALSE
${PROJECT_BINARY_DIR}/CMakeTmp
${PROJECT_BINARY_DIR}/CMake/SharedLibraryPathInfo.cxx
OUTPUT_VARIABLE OUTPUT # 会创建变量SHARED_LIBRARY_PATH_TYPE_TRYRUN_OUTPUT输出到屏幕
ARGS "LDPATH"
)
  • try_run()运行时会首先编译软件,然后检查CMAKE_CROSSCOMPILING变量来判断可执行文件能否在该平台上编译。
  • 在上面的例子中,一个源文件会被编译,编译结果会赋给两个变量中,还会创建一个变量SHARED_LIBRARY_PATH_TYPE_TRYRUN_OUTPUT,值可能为xxx-NOTFOUND。这个变量的值一般会通过标准流stdout或者stderr输出到屏幕。
  • 当CMake不能判断一些变量时,会在${CMAKE_BINARY_DIR}/TryRunResults.cmake中输出信息。
  • CMake会主动将可执行文件复制到相关目录下执行,文件会进行命名,一般为cmTryCompileExec-
  • 其实上面的过程也是给环境变量赋值的过程,更方便的方式,是使用TryRunResults.cmake文件,将其复制到一个安全路径下,给一个名字,比如TryRunResults-MyProject-eldk-ppc.cmake,编辑好后,可以直接加载,存到CMake Cache中,然后使用GUI编辑即可。
src/build/ $ cmake -C ~/TryRunResults-MyProject-eldk-ppc.cmake . # 变量已经在Cache中了,

没有操作系统的交叉编译

  • 没有多大改变,只不过需要烧写工具而已。

推荐阅读