在现代 CMake 中定义预处理器

Rok*_*nus 6 c++ preprocessor cmake

我目前正在学习 CMake,不想养成坏习惯,因为在 CMake 中总是有两种方法可以做某事(从我所看到的旧方法和现代方法)

阅读了有关 CMake 中预处理器的一些文档并检查了这篇文章后: 通过 cmake 定义预处理器宏

我得出的结论是,我可以将预处理器定义为:

  • add_compile_definitions(FOO)
  • target_compile_definitions(myTarget PRIVATE FOO)
  • add_definitions(-DFOO)

经过一些测试后,他们实际上一切都按预期工作并定义FOO

但现在我的问题是我应该使用的最“现代”的方式是什么以及每个函数之间的真正区别是什么,我注意到的唯一区别是如果我使用它然后在父目标中target_compile_definitions(myTarget PUBLIC FOO)定义。FOO

Rei*_*ica 9

现代 CMake 的总体趋势是从全局设置转向以目标为中心的设置。仅基于这条规则,target_compile_definitions()就是最现代的方法。它还允许控制设置是仅在目标中使用 ( PRIVATE)、在使用该目标的其他目标中使用 ( INTERFACE),还是在两者中使用 ( PUBLIC)。在内部,它通过修改目标的属性COMPILE_DEFINITIONS和来工作INTERFACE_COMPILE_DEFINITIONS

就现代性而言,下一个是add_compile_definitions()。它将宏定义添加到当前目录和子目录中定义的所有目标;其范围与include_directories()此类似。在内部,它通过修改COMPILE_DEFINITIONS当前目录的属性来工作。所以:它仍然使用正确的“现代”机制,但是是面向目录的而不是面向目标的。

在列表的底部,我们有非常古老的函数add_definitions()。在现代 CMake 中最好避免这种情况。虽然旨在指定预处理器定义(因此得名),但它实际上允许传递任意编译器选项(这也是您需要指定-DFOO而不是仅FOO作为其参数的原因)。它试图确定传入的内容是否实际上是预处理器宏定义,在这种情况下它们将被移动到目录的COMPILE_DEFINTIIONS属性中。如果它们没有被这样标识(对于具有复杂替换字符串的宏可能会发生这种情况),它们将保留在标志列表中。