良好的 CMake 风格:继承属性

Good CMake Style: Inherit Properties

Daniel Pfeifer,在他的演讲中 "Effective CMake", 指出一点,建议避免变量 尽可能多的定义。

现在,如何将属性放入各种构建中 目标。也就是说,例如

   target_include_directories(base_IncludeFlags
                              INTERFACE 
                              first/dir
                              second/dir
                              ...)

定义一组包含目录。而不是定义 target_atarget_b 的目录完全相同 和target_c,我想让那些目标继承 来自 'base_target' 的包含目录,类似

target_link_libraries(target_a PUBLIC base_IncludeFlags) 
target_link_libraries(target_b PUBLIC base_IncludeFlags)
target_link_libraries(target_c PUBLIC base_IncludeFlags)

其中 base_IncludeFlags 不应是真实的物理目标, 而是类似于 抽象基础 class 接口 .

另一方面,我不想使用include_directories 因为这会影响所有目标。是不是用foreach比较好? 最优雅的方法是什么?我可以做 base_target 库并添加依赖项?

What is the most elegant way to do this?

考虑到 CMake 文件通常由非 CMake 专家的人员阅读和编辑。与其追求优雅,不如考虑追求简单:保持简单,愚蠢。

如果你引入抽象,任何类型的隐藏隐式行为,每个人都将更难维护 CMake 文件。

对我来说,在这种情况下,简单意味着复制(复制)条目,如果只有 2-3 个条目的话。如果有更多库,我会把 header 放在一个变量中。 "Effective CMake" 演示文稿指出要避免 不必要的 、single-use 变量定义。我认为这个 header 列表将是一个有用的变量,值得创建。

What I want is a target that is not actually physically produced, but which propagates some common properties.

正是为了这个目的,CMake 有 INTERFACE library - 不同属性的容器,当这个库链接到另一个目标时传播这些属性。

示例:

# Create "container" target
add_library(base_target INTERFACE)

# Add some INTERFACE properties for that target
target_include_directories(base_target INTERFACE 
                          first/dir
                          second/dir)

# Some 'other_target' (library or executable) may easily consume all common properties:
target_link_libraries(other_target PUBLIC base_target)
# Now 'other_target' has aforementioned include directories too.
# Instead of PUBLIC other linking types (PRIVATE, INTERFACE) may be used.