由于篇幅问题本篇接着上文继续介绍 CMakeLists.txt 语法规则基础及常用指令。
- aux_source_directory
aux_source_directory 命令会查找目录中的所有源文件,其命令定义如下:
aux_source_directory(<dir> <variable>)
从指定的目录中查找所有源文件,并将扫描到的源文件路径信息存放到变量中,譬如目录结 构如下:
├── build
├── CMakeLists.txt
└── src
├── 1.c
├── 2.c
├── 2.cpp
└── main.c
CMakeCache.txt 内容如下所示:
# 顶层 CMakeLists.txt
cmake_minimum_required("VERSION" "3.5")
project("HELLO")
# 查找 src 目录下的所有源文件
aux_source_directory(src SRC_LIST)
message("${SRC_LIST}") # 打印 SRC_LIST 变量
进入到 build 目录下,执行 cmake ..命令,打印信息如下所示:
由此可见,aux_source_directory 会将扫描到的每一个源文件添加到 SRC_LIST 变量中,组成一个字符串列表,使用分号“;”分隔。
同理,aux_source_directory 既可以使用相对路径,也可以使用绝对路径,相对路径是相对于当前源码路径。
- get_target_property 和 set_target_properties
分别用于获取/设置目标的属性。
- include_directories include_directories
命令用于设置头文件的搜索路径,相当于 gcc 的-I 选项,其定义如下所示:
include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...])
默认情况下会将指定目录添加到头文件搜索列表(可以认为每一个 CMakeLists.txt 源码都有自己的头文 件搜索列表)的最后面,可以通过设置 CMAKE_INCLUDE_DIRECTORIES_BEFORE 变量为 ON 来改变它默认行为,将目录添加到列表前面。也可以在每次调用 include_directories 命令时使用 AFTER 或 BEFORE 选项来指定是添加到列表的前面或者后面。如果使用 SYSTEM 选项,会把指定目录当成系统的搜索目录。 既可以使用绝对路径来指定头文件搜索目录、也可以使用相对路径来指定,相对路径被解释为当前源码路径的相对路径。
譬如工程目录结构如下所示:
├── build
├── CMakeLists.txt
├── include
│ └── hello.h
└── main.c
源文件 main.c 中使用了 include 目录下的头文件 hello.h,CMakeLists.txt 内容如下:
# 顶层 CMakeLists.txt
cmake_minimum_required("VERSION" "3.5")
project("HELLO")
include_directories(include)
add_executable(hello main.c)
使用 include_directories 命令将当前目录下的 include 文件夹添加到头文件搜索列表中,进入 build 目录下,执行 cmake、make 进行构建、编译,编译过程是没有问题的,不会报错提示头文件找不到;但如果去掉 include_directories(include)这条命令,编译肯定会报错,大家可以动手试试!
默认情况下,include 目录被添加到头文件搜索列表的最后面,通过 AFTER 或 BEFORE 选项可显式指定添加到列表后面或前面:
# 添加到列表后面
include_directories(AFTER include)
# 添加到列表前面
include_directories(BEFORE include)
当调用 add_subdirectory 命令加载子源码时,会将 include_directories 命令包含的目录列表向下传递给子源码(子源码从父源码中继承过来),我们测试下,譬如工程目录结构如下所示:
├── build
├── CMakeLists.txt
├── include
│ └── hello.h
└── src
├── CMakeLists.txt
└── main.c
src 目录下 main.c 源文件中使用了 hello.h 头文件,顶层 CMakeLists.txt 内容如下所示:
# 顶层 CMakeLists.txt
cmake_minimum_required("VERSION" "3.5")
project("HELLO")
include_directories(include)
add_subdirectory(src)
顶层 CMakeLists.txt 源码中调用了 include_directories 将 include 目录添加到当前源码的头文件搜索列表中,接着调用 add_subdirectory 命令加载、执行子源码;src 目录下 CMakeLists.txt 内容如下所示:
# src 目录 CMakeLists.txt
add_executable(hello main.c)
进入到 build 目录,进行构建、编译,整个编译过程是没有问题的。
- link_directories 和 link_libraries link_directories
命令用于设置库文件的搜索路径,相当于 gcc 编译器的-L 选项;link_libraries 命令用于 设置需要链接的库文件,相当于 gcc 编译器的-l 选项;命令定义如下所示:
link_directories(directory1 directory2 ...)
link_libraries([item1 [item2 [...]]]
[[debug|optimized|general] <item>] ...)
link_directories 会将指定目录添加到库文件搜索列表(可以认为每一个 CMakeLists.txt 源码都有自己的库文件搜索列表)中;同理,link_libraries 命令会将指定库文件添加到链接库列表。link_directories 命令可以使用绝对路径或相对路径指定目录,相对路径被解释为当前源码路径的相对路径。
譬如工程目录结构如下所示:
├── build
├── CMakeLists.txt
├── include
│ └── hello.h
├── lib
│ └── libhello.so
└── main.c
在 lib 目录下有一个动态库文件 libhello.so,编译链接 main.c 源文件时需要链接 libhello.so;CMakeLists.txt 文件内容如下所示:
# 顶层 CMakeLists.txt
cmake_minimum_required("VERSION" "3.5")
project("HELLO")
include_directories(include)
link_directories(lib)
link_libraries(hello)
add_executable(main main.c)
库文件名既可以使用简写,也可以库文件名的全称,譬如:
# 简写
link_libraries(hello)
# 全称
link_libraries(libhello.so)
link_libraries 命令也可以指定库文件的全路径(绝对路径 /开头),如果不是/开头,link_libraries 会认为调用者传入的是库文件名,而非库文件全路径,譬如上述 CMakeLists.txt 可以修改为下面这种方式:
# 顶层 CMakeLists.txt
cmake_minimum_required("VERSION" "3.5")
project("HELLO")
include_directories(include)
link_libraries(${PROJECT_SOURCE_DIR}/lib/libhello.so)
add_executable(main main.c)
与 include_directories 命令相同,当调用 add_subdirectory 命令加载子源码时,会将 link_directories 命令包含的目录列表以及 link_libraries 命令包含的链接库列表向下传递给子源码(子源码从父源码中继承过来)。 这里不再演示了,大家可以自己测试下。
- list
list 命令是一个关于列表操作的命令,譬如获取列表的长度、从列表中返回由索引值指定的元素、将元素追加到列表中等等。命令定义如下:
list(LENGTH <list> <output variable>)
list(GET <list> <element index> [<element index> ...]
<output variable>)
list(APPEND <list> [<element> ...])
list(FIND <list> <value> <output variable>)
list(INSERT <list> <element_index> <element> [<element> ...])
list(REMOVE_ITEM <list> <value> [<value> ...])
list(REMOVE_AT <list> <index> [<index> ...])
list(REMOVE_DUPLICATES <list>)
list(REVERSE <list>)
list(SORT <list>)
列表这个概念还没给大家介绍,列表其实就是字符串数组(或者叫字符串列表、字符串数组),稍后再向大家说明。
LENGTH 选项用于返回列表长度;
GET 选项从列表中返回由索引值指定的元素;
APPEND 选项将元素追加到列表后面;
FIND 选项将返回列表中指定元素的索引值,如果未找到,则返回-1。
INSERT 选项将向列表中的指定位置插入元素。
REMOVE_AT 和 REMOVE_ITEM 选项将从列表中删除元素,不同之处在于 REMOVE_ITEM 将删除给定的元素,而 REMOVE_AT 将删除给定索引值的元素。
REMOVE_DUPLICATES 选项将删除列表中的重复元素。
REVERSE 选项就地反转列表的内容。
SORT 选项按字母顺序对列表进行排序。
- message
message 命令用于打印、输出信息,类似于 Linux 的 echo 命令,命令定义如下所示:
message([] "message to display" ...)
可选的 mode 关键字用于确定消息的类型,如下:
mode | 说明 |
none(无) | 重要信息、普通信息 |
STATUS | 附带信息 |
WARNING | CMake 警告,继续处理 |
AUTHOR_WARNING | CMake 警告(开发),继续处理 |
SEND_ERROR | CMake 错误,继续处理,但跳过生成 |
FATAL_ERROR | CMake 错误,停止处理和生成 |
DEPRECATION | 如果变量 CMAKE_ERROR_DEPRECATED 或 CMAKE_WARN_DEPRECATED 分别启用,则 CMake 弃用错误或警告,否则没有消息。 |
所以可以使用这个命令作为 CMakeLists.txt 源码中的输出打印语句,譬如:
# 打印"Hello World"
message("Hello World!")
未完待续...