2017-06-20 54 views
2

有谁知道在CMake文件中应用“包含一次”模式的简单方法吗?在C/C++中,它曾经在头文件的开始和结尾需要一个#ifdef/#endif对,直到#pragma一度变得很普遍。当然,也可以在CMake中做同样的事情,但是我认为如果它不需要明确的条件语句会更好。是否有包含一次cmake文件的命令?

重编:看起来,return()命令应该这样做。我会定义一个这样的宏:

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

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

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

+1

什么是在CMake的文件你包括,你的设置是什么,你*会*要求防止多重包含?就个人而言,我通常拥有“main”CMakeLists.txt(它不包含“包含”)和带有辅助函数的模块(不会抱怨首先包含多个包含)。在这里,我不太清楚用例是什么。 – DevSolar

+0

有各种各样的情况可能是必要的。具体来说,我有一个包含子目录的顶级项目,我想让每个子目录成为一个独立项目。所以顶级项目和所有的子级都包含一个共享的定义文件。如果定义文件打印的东西,它打印得比我想要的多得多。这是一个处理开销。等等。所以,我认为有充足的理由要求这样做。 –

+0

如果子目录是作为独立项目构建的 - 每个项目的输出应该是独立完成的 - 或者处理开销的影响(即使对于大多数涉及的项目我都认为是微不足道的,我不相信印刷信息的冗余)用CMake处理,尽管我总是从一个单独的CMakeLists.txt构建(包含)。但我愿意让这个休息一下,指出Tsyvarev在“如何”和“为什么”这两个方面的出色答案。 – DevSolar

回答

0

它明确规定 Refer Here更多信息here

include(<file|module> [OPTIONAL] [RESULT_VARIABLE <VAR>] 
        [NO_POLICY_SCOPE]) 
+4

问题是关于“包含**一次**”。这并没有回答这个问题。 – DevSolar

3

对多个模块包括最简单的保护图案会

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

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

if(COMMAND foo_func) 
    return() 
endif() 

你真的需要警卫吗?

依赖于模块中定义的事情,模块可能需要保护多次包含或不包含。

在许多简单的情况下,警卫不需要:即使包含多次,模块的代码也可以工作。

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

  1. 甲模块定义了一个函数:保护被不需要

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

  2. 甲模块定义了一个恒定变量:保护被不需要

    与功能一样,CMake允许多次定义变量。

    但是,如果你在这种情况下,使用保护,它应该检查参数,而不是一个函数:

    if(foo_var) 
        return() 
    endif() 
    

    这是因为函数有全球知名度,但变量有当地的知名度。也就是说,如果你的模块将被包含到其他子树中,该函数将在该子树中已经可见,但该变量不是。

  3. 模块经由set(CACHE)限定全局变量:后卫是如果变量被定义为set(CACHE INTERNAL)只需要

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

  4. 模块定义全球房地产:是需要后卫。

请注意,如果您的模块使用简单(没有CACHE)变量作为全球性的,它不能在多个子树工作,所以后卫应该是

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