Cmake·

[#5][Adding Usage Requirements for a Library][A菌严肃的CMake手记]

美式A菌

美式A菌

81 1

今日是2025年的1月2日,是2025年的第一個做工日,在開始學習之前呢,先要祝大家新年快樂,學有所成嘍。

Intro

先来复习一下吧~

  • add_library(): ?
  • add_subdirectory(): ?
  • target_link_libraries(): ?
  • PROJECT_SOURCE_DIR: ?
  • if()endif(): ?
  • list(),APPEND: ?
  • option(): ?
  • target_compile_definitions(): ?
  • cmake -D[OPTION_NAME]=: ?

  • add_library(): 设定一个程式为 Lib 库。
  • add_subdirectory(): 为项目增加一个子目录。
  • target_link_libraries(): 将一个或多个库链接到指定的目标(如可执行文件或另一个库)。
  • PROJECT_SOURCE_DIR: 程式源码的目录。
  • if()endif(): 条件判断。
  • list(),APPEND: 扫描和追加。
  • option(): 设定选项。
  • target_compile_definitions(): 向程式添加预处理器宏。
  • cmake -D[OPTION_NAME]=: 为 CMakeLists.txt 中的 option 填充值。

那么今天我们来学习一下CMake如何为Lib添加使用要求和自动配置一些参数的?

涉及到的函式(函数 / API) 如下:

  • target_include_directories()
  • target_link_libraries()
  • INTERFACE

那学习本节内容还需要一些前提条件:

  • 你可以直接使用上节内容中的代码。
  • 也可以从Code获取初始代码哦。

Tips: 根据代码提示完成步骤,我们可以在上面的链接中查看MathFuntions/CMakeLists.txt文本档案中的内容,其中包含对代码的解释说明# TODO 1: State that anybody linking to MathFunctions needs to include the,# TODO 6: Link SqrtLibrary to tutorial_compiler_flags,# TODO 7: Link MathFunctions to tutorial_compiler_flags我们也可以根据这些提示自行查找资料完成CMake的编写来自己学习呦。 A菌也是跟随官方实例来学习的,所以哪里有疑惑也可以自行对照校对,如果文章有出入或者A菌有解释不清或错误,请留言帮助A菌改正啦。

开始

Setp1: 第三方Lib自己处理包含目录,减少使用者负担

  • MathFunctions 指定所需的包含目录。
    • MathFunctions/CMakeLists.txt 末尾,将 target_include_directories()INTERFACE 关键字一起使用。
# TODO 1: State that anybody linking to MathFunctions needs to include the
#
# 这句代码的意思是将 `MathFunctions` 目标的当前源目录(`${CMAKE_CURRENT_SOURCE_DIR}`)添加到 #`MathFunctions` 目标的包含目录中,并且这个包含目录是以 `INTERFACE` 的形式添加的。
#
#`INTERFACE` 的意思是这个包含目录信息将会传播给所有链接到 `MathFunctions` 的目标。
# 也就是说,任何链接到 #`MathFunctions` 的目标(例如 `Tutorial`)都会自动包含 `MathFunctions` 的当前源目录作为它们的包含目录。

target_include_directories(MathFunctions INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})

  • Tutorial 只需链接到 MathFunctions 而不必担心任何其他包含目录。
    • 从顶级 CMakeLists.txt 中删除对 EXTRA_INCLUDES 变量的使用。
# TODO 2: Remove EXTRA_INCLUDES list

# add the MathFunctions library
add_subdirectory(MathFunctions)

# 这里注释掉了,不用包含了,因为链接的时候库会自己处理包含目录了
# list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/MathFunctions")

  • 删除顶级CMakeLists.txt中的target_include_directories中的EXTRA_INCLUDES变量
# TODO 3: Remove use of EXTRA_INCLUDES

# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
#
# target_include_directories(Tutorial PUBLIC
#                            "${PROJECT_BINARY_DIR}"
#                            ${EXTRA_INCLUDES}
#                            )
# 这里删除了 ${EXTRA_INCLUDES} 变量,因为list追加的已经没了,库也自包含了只需要链接就可以了。
target_include_directories(Tutorial PUBLIC
                           "${PROJECT_BINARY_DIR}"
                           )

step2: 一对多的Lib配置

  • 顶级CMakeLists.txt
  • 创建一个新的lib使用INTERFACE修饰,这样所有的其他代码库链接到它的时候,就都被cxx_std_11约束啦。
  • 删除掉set中依靠环境变量对版本的约束。
# TODO 4: Replace the following code by:
# * Creating an interface library called tutorial_compiler_flags
#   Hint: use add_library() with the INTERFACE signature
# * Add compiler feature cxx_std_11 to tutorial_compiler_flags
#   Hint: Use target_compile_features()

# specify the C++ standard
# 注释掉之前用set设置的环境变量的约束
# set(CMAKE_CXX_STANDARD 11)
# set(CMAKE_CXX_STANDARD_REQUIRED True)

# 创建一个新的 Lib 名为`tutorial_compiler_flags`亦或是其他
add_library(tutorial_compiler_flags INTERFACE)

# `target_compile_features` 是 CMake 中用于指定目标所需的编译特性的命
# 令。它允许你为目标设置特定的编译器特性,例如 C++ 标准版本。

# 这行代码的意思是为 `tutorial_compiler_flags` 接口库添加 `cxx_std_11` 
# 编译特性,这意味着任何链接到 `tutorial_compiler_flags` 的目标都需要支
# 持 C++11 标准。

# `target_compile_features` 的常见用法包括:
# * `PRIVATE`:仅当前目标需要这些编译特性。
# * `PUBLIC`:当前目标和所有链接到它的目标都需要这些编译特性。
# * `INTERFACE`:仅链接到当前目标的目标需要这些编译特性。
target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11)

  • 顶级CMakeLists.txt
  • 将我们的通用约束库链接到程式中,以传播设置。
# TODO 5: Link Tutorial to tutorial_compiler_flags
# 
# 这行代码的意思是将 `MathFunctions` 和 `tutorial_compiler_flags` 库链
# 接到 `Tutorial` 可执行文件,并且这些链接是以 `PUBLIC` 的形式添加的。
#
# `PUBLIC` 的意思是:
# * 任何链接到 `Tutorial` 的目标也会继承这些链接库。

target_link_libraries(Tutorial PUBLIC MathFunctions tutorial_compiler_flags)
  • MathFunctions/CMakeLists.txt
  • 链接一下
# 从这里开的if然后省略了写内容
if (USE_MYMATH)...

# TODO 6: Link SqrtLibrary to tutorial_compiler_flags

# 链接`tutorial_compiler_flags`到`SqrtLibrary`
# `target_link_libraries` 命令用于指定目标需要链接的库。
# 这里使用 `PUBLIC` 关键字的原因是为了确保依赖关系能够传播到任何链接到 `SqrtLibrary` 的目标。
# * `PRIVATE`:依赖关系仅用于目标本身。
# * `INTERFACE`:依赖关系仅用于链接到该目标的其他目标。
# * `PUBLIC`:依赖关系既用于目标本身,也用于链接到该目标的其他目标。
  target_link_libraries(SqrtLibrary PUBLIC tutorial_compiler_flags)

# 链接`SqrtLibrary`到`MathFunctions`并且被`tutorial_compiler_flags`传播了
  target_link_libraries(MathFunctions PRIVATE SqrtLibrary)
endif()

# TODO 7: Link MathFunctions to tutorial_compiler_flags
# 这一行的作用是将 `tutorial_compiler_flags` 的设置传播到任何链接到 `MathFunctions` 的目标。
# 这是因为 `PUBLIC` 关键字会将依赖关系传播到所有依赖 `MathFunctions` 的目标。
target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags)

如此一来,我们想更改编译设置的时候,只需要修改tutorial_compiler_flags即可。

复习

  • target_include_directories(x option ${CMAKE_CURRENT_SOURCE_DIR}): 指定任何链接到 x 的目标需要包含当前源目录 (${CMAKE_CURRENT_SOURCE_DIR}) 作为头文件搜索路径。
    • option: 可选 INTERFACE,PRIVATE,PUBLIC
  • target_link_libraries(x option y): 将y链接到x
    • option: 可选 INTERFACE,PRIVATE,PUBLIC

所属系列

从当前文章继续阅读它所在合集中的前后内容。

相关文章

优先推荐同专题、同标签和同作者内容,补足热门文章。

评论 1

登录 后参与评论

评论 1

美式A菌
美式A菌1月2日 18:02

論壇的錯誤真的有夠多誒。