Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 现代CMake中预处理器的定义_C++_Cmake_Preprocessor - Fatal编程技术网

C++ 现代CMake中预处理器的定义

C++ 现代CMake中预处理器的定义,c++,cmake,preprocessor,C++,Cmake,Preprocessor,我目前正在学习CMake,不想养成坏习惯,因为在CMake中总有两种方法可以做某事(从我所看到的来看,旧方法和现代方法) 在阅读了一些关于CMake中预处理器的文档并查看本文之后: 我得出的结论是,我可以将预处理器定义为: add\u compile\u定义(FOO) target\u compile\u定义(myTarget PRIVATE FOO) 添加定义(-DFOO) 在一些测试之后,它们确实按照预期工作,并定义FOO 但现在我的问题是,我应该使用哪种最“现代”的方式,以及每个函数

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

在阅读了一些关于CMake中预处理器的文档并查看本文之后:

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

  • add\u compile\u定义(FOO)

  • target\u compile\u定义(myTarget PRIVATE FOO)
  • 添加定义(-DFOO)
在一些测试之后,它们确实按照预期工作,并定义
FOO


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

现代CMake的总趋势是从全局设置转向以目标为中心的设置。仅基于这一规则,
target\u compile\u definitions()
是最现代的方法。它还允许控制设置是仅在目标(
PRIVATE
)中使用,还是在使用此目标的其他目标(
INTERFACE
)中使用,还是同时在两者中使用(
PUBLIC
)。在内部,它通过修改目标的属性
COMPILE\u DEFINITIONS
INTERFACE\u COMPILE\u DEFINITIONS
来工作

下一个关于现代性的问题是
add\u compile\u definitions()
。将宏定义添加到当前目录和子目录中定义的所有目标中;在这方面,其范围类似于
include_directories()
。在内部,它通过修改当前目录的
COMPILE\u DEFINITIONS
属性来工作。所以:它仍然使用正确的“现代”机制,但是是面向目录的,而不是面向目标的


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

事实上,
target\u compile\u definitions
是添加预处理宏的最合适的方法


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


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

如何使用
目标编译定义
添加与
定义3.21版
等价的内容(myTarget PUBLIC VER=3.21)
应该可以做到这一点。