摘要:本文介绍了如何通过现代 CMake 语法设置目标的使用要求,以便更好地管理库和可执行文件的编译、链接及包含路径等属性。使用要求命令如 target_compile_definitions()
、target_include_directories()
、target_link_libraries()
等,允许精确控制编译器和链接器的行为。文章通过重构一个 CMake 项目示例,展示了如何设置库的包含目录、使用 INTERFACE
库来定义编译选项以及链接多个库。此外,还详细解释了 target_include_directories()
的使用场景,包括如何为目标设置私有、公共或接口包含目录。
文章目录
目标参数的使用要求(Usage Requirements)允许更好地控制库或可执行文件的链接和 include
行,同时也可以更好地控制 CMake 中目标的传递属性。使用要求指的是某个目标(如库或可执行文件)在被其他目标使用时,需要满足的条件或要求,比如包含路径、编译选项、链接库等。这些要求定义了目标对外暴露的接口,以及在链接其他目标时如何传递这些属性。举一个例子,例如我们制造一个物理部件供别人使用,使用要求就是这个物理部件的使用说明书,告诉客户应该怎么使用这个物理部件。
利用使用要求的主要命令是:
target_compile_definitions()
:用于向指定的目标(库、可执行文件等)添加编译选项。这可以使我们对特定的目标定制某些编译选项,这些选项不会影响到其它目标。例如:
add_library(MyLibrary STATIC mylibrary.cpp)
target_compile_options(MyLibrary PRIVATE -Wall -Wextra -Werror)
以上命令只向 MyLibrary
这个库添加私有编译选项。
target_include_directories()
:用于向指定的目标添加包含目录,这些目录是编译器在搜索头文件时应该查找的路径。target_link_directories()
:原本用于向指定的目标(target)添加链接器搜索库的路径(linker search directories),会影响到链接器全局的搜索路径列表。但在 CMake 3.12 之后的版本,更推荐使用target_link_libraries()
。target_link_options()
:为目标(可执行文件、动态链接库和模块库(module library))的链接步骤添加选项。target_precompile_headers()
:添加需要进行预编译的头文件列表target_sources()
:向指定的目标添加源文件。这使得我们可以在定义目标之后,仍然能够向其中添加或修改源文件列表,而无需重新定义整个目标。这对于构建系统需要动态地包含或排除源文件时特别有用。
本节我们使用现代 CMake 语法重构 CMake教程(二):创建并使用库。
在上一节中,当可执行文件使用 MathFunctions
库时,顶层的 CMake 文件需要包含这个库所在的目录。本节我们在自定义的库中定义它自己的使用要求,以便在必要时将其传递给其他目标。简言之,就是在 MathFunctions
子目录下的 CMake 文件当中指定包含目录。这样使用 MathFunctions
库的目标只需要链接这个库,而不需要再添加 include
目录。
本节所用的材料是官网提供的源代码目录下的 Step3
。
下面的两个练习,将要完成的功能:
- 生成
MathFunctions
库的 CMake 文件指定include
路径。这样使用这个库的目标,在使用target_include_directories()
是就不用再指定MathFunctions
的目录。 - 使用
INTERFACE
库指定生成目标时所使用的 C++ 标准。这样就可以为每个目标单独设置编译器编译时的选项。
1. 添加库的使用要求
按照如下步骤修改相应的文件:
MathFunctions/CMakeLists.txt
target_include_directories(MathFunctions
INTERFACE ${
CMAKE_CURRENT_SOURCE_DIR}
)
${CMAKE_CURRENT_SOURCE_DIR}
是指当前被处理的源目录的路径。
2. 顶层 CMakeLists.txt
target_include_directories(Tutorial PUBLIC
"${PROJECT_BINARY_DIR}"
)
可以看到,此时可以不用再加上"${PROJECT_SOURCE_DIR}/MathFunctions"
。
2. 使用 INTERFACE
库设置 C++ 标准
按照如下步骤修改相应的文件:
- 修改顶层的
CMakeLists.txt
文件:
add_library(tutorial_compiler_flags INTERFACE