在现代CMake中定义预处理器

时间:2019-04-05 13:08:17

标签: c++ cmake preprocessor

我目前正在学习CMake,并且不想养成不良习惯,因为在CMake中总有两种方法可以做某事(根据我所见,这是旧方法还是现代方法)

在阅读了有关CMake中的预处理器的一些文档并检查了这篇文章之后: Define preprocessor macro through cmake

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

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

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

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

2 个答案:

答案 0 :(得分:3)

现代CMake的总体趋势是从全局设置转移到以目标为中心的设置。仅基于此规则,XDocument doc = XDocument.Load(filePath); List<string> names = doc.Descendants("Name").Select(x => x.Value).ToList(); 是最现代的方法。它还允许控制设置是仅在目标(target_compile_definitions())中使用,还是在使用该目标的其他目标(PRIVATE中使用,或在两个目标(INTERFACE中使用)。在内部,它通过修改目标的属性PUBLICCOMPILE_DEFINITIONS来起作用。

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

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

答案 1 :(得分:2)

实际上,target_compile_definitions是添加预处理宏的最适当方法。

target_compile_definitions(myTarget PUBLIC FOO)传播FOO到依赖项的原因也是您应使用它的原因之一,因为您可以按目标而不是每个文件夹正确定义它们。现在,您可以将这些定义附加到目标,以便依赖项也可以声明它们。如果尝试从不同的文件夹创建目标,则将更精确地看到此行为,并且实际上比以前非常不可靠的行为更有意义。

例如,在Windows上,所有常规的“导出”宏都应以这种方式声明,并PRIVATE声明,这样它们就不会传播,因为它们实际上是私有定义。