我目前正在学习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 }}在父目标中。
答案 0 :(得分:3)
现代CMake的总体趋势是从全局设置转移到以目标为中心的设置。仅基于此规则,XDocument doc = XDocument.Load(filePath);
List<string> names = doc.Descendants("Name").Select(x => x.Value).ToList();
是最现代的方法。它还允许控制设置是仅在目标(target_compile_definitions()
)中使用,还是在使用该目标的其他目标(PRIVATE
中使用,或在两个目标(INTERFACE
中使用)。在内部,它通过修改目标的属性PUBLIC
和COMPILE_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
声明,这样它们就不会传播,因为它们实际上是私有定义。