• include_directories 会告诉 编译器 在哪里查找头文件
  • link_directories 会告诉 链接器 要链接哪些库与您的可执行文件
  • link_libraries用在add_executable之前,target_link_libraries用在add_executable之后,毕竟target_link_libraries要先生成出一个 target 来先。

使用CMake进行交叉编译,只需要几条指令即可

#### CrossCompiler.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++)

使用方式

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

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


  • 本机程序需要链接系统中的 opencv 库,可以使用 cmake 提供的find_package(OpenCV REQUIRED),交叉编译的时候就不能这样用了,因为arm linux 嵌入式开发板往往无法构建和安装 opencv 。只能用编译工具链将opencv源码编译链接到可执行文件中去

  • 这就牵涉到链接库的顺序问题,链接库的时候顺序很重要,这两个参数让这个顺序问题不再那么重要
  • 正常情况下,链接的时候库文件只会按照它们出现在命令行的顺序搜索一遍,如果有未定义的引用标号,而该标号还放在命令行的后面,这样链接器就无法解决该标号的引用问题。加上这两个就可以避免多个包之间互相引用的问题。

在写交叉编译.cmake文件时,遇到"CACHE STRING"

  • 参考博文
  • 这就牵涉到 cmake 缓存变量这个知识点了
    • Normal Variable,普通变量,相当于一个局部变量。在同一个CMake工程中使用,会有作用域限制或区分。
    • Cache Variable,缓存变量,相当于一个全局变量。在同一个CMake工程中任何地方都可以使用。
    • CACHE STRING 就是定义一个 STRING 类型的缓存变量

将项目编译成可以debug的版本

SET(CMAKE_BUILD_TYPE “Debug”)

CMake 中的 if 语句

  • CMake 文档对 if 语句的解释

if(<constant>)
True if the constant is 1, ON, YES, TRUE, Y, or a non-zero number. False if the constant is 0, OFF, NO, FALSE, N, IGNORE, NOTFOUND, the empty string, or ends in the suffix -NOTFOUND. Named boolean constants are case-insensitive. If the argument is not one of these constants, it is treated as a variable.
if(<variable>)
True if the variable is defined to a value that is not a false constant. False otherwise. (Note macro arguments are not variables.)

  • 也就是说, 在if 语句中, 它先把它看作<constant>, 如果不是<constant>再看作<variable>.
#unset表示没有定义它, 如果没有定义前, 你就使用它, 在cmake里都默认用空串表示
unset(BLA)
set(FOO "BLA")
if(FOO)
    message("if(<variable>): True")
else()
    message("if(<variable>): False")
endif()

if(${FOO})
    message("if(<constant>): True")
else()
    message("if(<constant>): False")
endif()
  • 上面的输出为:
if(<variable>): True
if(<constant>): False

CMake 中的 set 语句

  • 在cmake里, 你可以把所有的变量都看作字符串 / 字符串列表. 像这样, "xxxx" 或者 "xxx1;xxx2;xxx3"分号分割, 本质上都可以看作字符串.
# 它类似与cpp里 std::string foo = "BLA";
set(FOO "BLA")
set(FOO BLA)
# var1是个字符串, var2是个字符串列表, 另外注意在message输出时,
# 最好加上双引号, 你可以对比一下 不加双引号和加双引号的输出对比.
# var1="x"
# var2="a;b;c;d;e"
set(var1 x)
set(var2 a b c d e)
message("var1=${var1}")
message("var2=${var2}")