cmake文件是否包含一次命令?

时间:2017-06-20 06:22:48

标签: cmake

有没有人知道一种简单的方法来应用"包含一次" CMake文件中的模式?在C / C ++中,它曾经在头文件的开头和结尾需要#ifdef / #endif对,直到#pragma一度变得普遍。当然,可以在CMake中做同样的事情,但我认为如果它不需要明确的条件声明就会很好。

重新编辑:似乎应该执行return()命令。我定义了一个像这样的宏:

macro(include_once)
  if (INCLUDED_${CMAKE_CURRENT_LIST_FILE})
    return()
  endif()
  set(INCLUDED_${CMAKE_CURRENT_LIST_FILE} true)
endmacro()

在文件开头使用宏,不带任何参数。因为它是一个宏,所以返回来自文件的include命令,而不是来自宏本身。

请注意,创建的变量有一个奇怪的名称,但CMake似乎接受了这个。

2 个答案:

答案 0 :(得分:4)

针对多个模块的最简单的保护模式将是

if(<something-which-is-defined-in-your-module>)
    return()
endif()

例如,如果你的CMake模块定义了一个函数foo_func,你可以使用这个警卫:

if(COMMAND foo_func)
    return()
endif()

你真的需要一名警卫吗?

依赖于模块中定义的内容,模块可能需要再次进行多次包含保护。

在许多简单的情况下,不需要 :即使包含多次,模块的代码也能正常工作。

但在其他一些情况下,错误的保护可能会破坏受保护模块的使用。

  1. 模块定义功能:后卫不需要

    CMake允许多次定义函数和宏。

  2. 模块定义常量变量:guard 不需要

    与函数一样,CMake允许多次定义变量。

    但是如果你在这种情况下使用后卫,它应该检查变量,而不是函数:

    if(foo_var)
        return()
    endif()
    

    这是因为函数具有全局可见性,但变量具有本地可见性。也就是说,如果您将模块包含在其他子树中,该函数将在该子树中可见,但该变量不是。

  3. 模块通过set(CACHE)定义全局变量:仅当变量定义为set(CACHE INTERNAL)时才需要

    通过例如set(CACHE STRING)find_library定义的变量不需要警卫。

  4. 模块定义全局属性:guard 需要

  5. 注意,如果你的模块使用简单的(不是 CACHE )变量作为全局变量,它不能在多个子树中工作,所以后卫应该是

        if(foo_var)
            message(SEND_ERROR "Module <...> cannot be included twice")
        endif()
    

答案 1 :(得分:2)

我曾经使用其他人建议的逻辑作为解决方案。然后我了解到cmake内置了此功能。

看看include_guard()。我相信这会做您想要的。