include_directories 与 link_directories 有什么区别
- include_directories 会告诉 编译器 在哪里查找头文件
- link_directories 会告诉 链接器 要链接哪些库与您的可执行文件
link_libraries 和 target_link_libraries的区别
- 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源码编译链接到可执行文件中去
有时候target_link_libraries 中会遇到这样的编译参数 -Wl,--start-group以及-Wl,--end-group
- 这就牵涉到链接库的顺序问题,链接库的时候顺序很重要,这两个参数让这个顺序问题不再那么重要
- 正常情况下,链接的时候库文件只会按照它们出现在命令行的顺序搜索一遍,如果有未定义的引用标号,而该标号还放在命令行的后面,这样链接器就无法解决该标号的引用问题。加上这两个就可以避免多个包之间互相引用的问题。
在写交叉编译.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}")