【CMake 入门与进阶(4)】 CMakeLists.txt 语法规则基础及部分常用指令-续(附使用代码)

        由于篇幅问题本篇接着上文继续介绍 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!")

未完待续...

猜你喜欢

转载自blog.csdn.net/cj_lsk/article/details/131062552
今日推荐