练习1 -为库添加使用需求
目标参数的使用要求允许对库或可执行文件的链接和包含行进行更好的控制,同时也允许对CMake中目标的传递属性进行更多的控制。
本节使用的示例代码见step1-简单开始cmake实践-CSDN博客。
目标
添加库的使用需求。
在这个练习中,我们将从添加库中重构代码,让库定义自己的使用需求,以便在必要时将它们传递给其他目标。在这种情况下,MathFunctions将指定任何所需的包含目录,目标Tutorial只需要链接到MathFunctions,而不必担心任何额外的include目录。
实践源代码在Step3目录中提供。在这个练习中,完成TODO 1到TODO 3。
首先,在MathFunctions/CMakeLists中添加对target_include_directories()的调用。记住,CMAKE_CURRENT_SOURCE_DIR是当前正在处理的源目录的路径。
然后,简化顶层CMakeLists.txt中对target_include_directories()的调用。
我们想声明,任何链接到MathFunctions的人都需要包含当前源目录,而MathFunctions本身不需要该目录。这可以用INTERFACE使用需求来表示。
在MathFunctions/CMakeLists.txt的末尾,使用target_include_directories()和INTERFACE关键字,如下所示:
// TODO 1: MathFunctions/CMakeLists.txt
target_include_directories(MathFunctions
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
)
现在我们已经指定了MathFunctions的使用需求,我们可以安全地从顶层的CMakeLists.txt中删除对EXTRA_INCLUDES变量的使用。
删除这一行:
// TODO 2: CMakeLists.txt
list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/MathFunctions")
并从target_include_directories中删除EXTRA_INCLUDES:
// TODO 3: CMakeLists.txt
target_include_directories(Tutorial PUBLIC
"${PROJECT_BINARY_DIR}"
)
注意,使用这种技术,我们的可执行目标使用我们的库所做的唯一事情就是用库目标的名称调用target_link_libraries()。在较大的项目中,手动指定库依赖项的经典方法很快就会变得非常复杂。
编译并运行
创建一个名为Step3_build的新目录,使用如下的命令:
mkdir Step3_build
cd Step3_build
cmake ../Step3
cmake --build .
练习2 -使用接口库设置c++标准
既然我们已经将代码转换为更现代的方法,那么让我们演示一种为多个目标设置属性的方法。
目标
添加一个INTERFACE库目标来指定所需的c++标准。
步骤
从我们在第3步练习1结束时留下的内容开始这个练习,必须完成TODO 4到TODO 7。
首先编辑顶层的CMakeLists.txt文件。构造一个名为tutorial_compiler_flags的INTERFACE库目标,并指定cxx_std_11作为目标编译器特性。
修改CMakeLists.txt和MathFunctions/CMakeLists.txt,以便所有目标都有一个target_link_libraries()调用tutorial_compiler_flags。
操作
让我们更新上一步的代码,使用接口库来设置c++需求。
首先,我们需要删除变量CMAKE_CXX_STANDARD和CMAKE_CXX_STANDARD_REQUIRED上的两个set()调用。具体要删除的行如下:
// CMakeLists.txt
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
接下来,我们需要创建一个接口库tutorial_compiler_flags。然后使用target_compile_features()来添加编译器特性cxx_std_11。
// TODO 4: CMakeLists.txt
add_library(tutorial_compiler_flags INTERFACE)
target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11)
最后,设置好接口库后,我们需要将可执行教程、SqrtLibrary库和MathFunctions库链接到新的tutorial_compiler_flags库。
// TODO 5: CMakeLists.txt
target_link_libraries(Tutorial PUBLIC MathFunctions tutorial_compiler_flags)
// TODO 6: MathFunctions/CMakeLists.txt
target_link_libraries(SqrtLibrary PUBLIC tutorial_compiler_flags)
// TODO 7: MathFunctions/CMakeLists.txt
target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags)
使用这种方法,我们可以明确哪些目标需要特定的需求。
编译并运行
由于我们已经在练习1中配置了编译目录,只需通过调用以下命令重新编译代码:
cd Step3_build
cmake --build .
然后,可以执行编译后的可执行文件,验证是否可以正常工作。