cmake:如何检查预处理器是否已定义

9

我无法让cmake测试预处理器是否已定义。例如:

cmake_minimum_required(VERSION 2.8.9)
project (cmake-test)
add_definitions(-DOS=LINUX)

if(NOT <what condition goes here?>)
    message(FATAL_ERROR "OS is not defined")
endif()

以下测试不起作用:
if (NOT COMMAND OS)
if (NOT DEFINED OS)
if (NOT OS)

我可以通过使用set()并测试常规的cmake变量,然后定义预处理宏来使其工作。例如:

set(OS LINUX)
if (OS)
    add_definitions(-DOS=${OS})
else()
    message(FATAL_ERROR "OS is not defined")
endif()

如果你想知道为什么我需要测试变量/预处理器是否在同一个文件中,原因是在最终实现中,这些将来自于被包含在主CMakeFile.txt中的外部文件。例如:

include(project_defs.txt)
if (OS)
    ....

预处理器是什么意思?CMake没有预处理器... - usr1234567
1
CMake会自动定义几个变量,用于描述系统。因此,您可以检查这些变量(在if命令中)以包含依赖于操作系统的代码。请参阅提供信息的变量 - Tsyvarev
@usr1234567,通过预处理器,我指的是由gcc-D选项定义的变量(与#define相同)。 - Mandeep Sandhu
@Tsyvarev OS 只是一个例子。我试图定义我的项目的自定义属性,因此 cmake 不会知道它们。 - Mandeep Sandhu
那么,你的方法(设置CMake变量,然后检查它)有什么问题吗?如果通过include()命令包含cmake脚本,则调用者可以看到所有定义。(他们说,include()不会引入变量定义范围)。 - Tsyvarev
@Tsyvarev 没有什么实质性的“问题”。只是有些啰嗦,因为我首先必须执行 set(),然后检查其是否存在,再执行 add_definitions()。能够只调用一次add_definitions()会更好。我仍在探索 @arrowd 的答案,使用 get_target_property() 并检查 COMPILE_DEFINITIONS 属性。 - Mandeep Sandhu
2个回答

4

这是为了完善arrowd的回答。

我也尝试了arrowd提到的COMPILE_DEFINITIONS选项,但没有成功。

根据CMake的文档,至少对于3.x版本,在CMake中调用add_definitions()时,它会将定义添加到COMPILE_DEFINITIONS目录属性中。

因此,假设您正在按照代码定义以下内容:

add_definitions(-DOS=LINUX)

为了从变量“MYDEFS”中检索已添加定义的字符串,您可以在CMake中使用以下代码行:
get_directory_property(MYDEFS COMPILE_DEFINITIONS)
MESSAGE( STATUS "Compile defs contain: " ${MYDEFS} )

然后,您可以检查${MYDEFS}中是否存在您要查找的定义。例如:
if(MYDEFS MATCHES "^OS=" OR MYDEFS MATCHES ";OS=")
    MESSAGE( STATUS "OS defined" )
else()
    # You can define your OS here if desired
endif()

由于可能添加多个定义,${MYDEFS} 包含多个变量,而不带引号的 ${MYDEFS} 会出现混乱。我建议使用 "${MYDEFS}" - ChrisZZ

2

通常情况下,传递给编译器的所有定义都由CMake控制。也就是说,您需要使用CMake变量创建这些定义:

option(SOMEFEATURE "Feature description" ON)

或者

set(OS "" CACHE STRING "Select your OS")

用户可以通过在CMake GUI中设置或者使用命令cmake -D OS=DOS来设置。然后,您可以使用if()运算符有条件地将add_definitions()添加到编译器命令行中。
更新:
如果您真的想访问预处理器标志,那么有一个COMPILE_DEFINITIONS目标属性。您可以通过以下方式访问它:
get_target_property(OUTVAR target COMPILE_DEFINITIONS)

1
那么我提到的第二种方法可能是唯一的方式了。如果cmake允许通过add_definitions设置测试内容,那就太好了。 - Mandeep Sandhu
谢谢您的更新。我确实查看了COMPILE_DEFINITIONS,因为add_definitions()的文档提到了它。但是,我无法获取指定的定义(我尝试了您使用get_target_property的建议,但是得到了NOTFOUND)。我正在使用cmake 2.8.12.2 - Mandeep Sandhu
这很奇怪,因为即使对于2.8版本,也存在此属性:https://cmake.org/cmake/help/v2.8.12/cmake.html#prop_tgt:COMPILE_DEFINITIONS 尝试使用更新的CMake。 - arrowd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接