【问题标题】:Can I control sources exclusion from target_sources in CMake?我可以控制 CMake 中 target_sources 的源排除吗?
【发布时间】:2021-06-22 00:20:44
【问题描述】:

我是 CMake 的新手,我想知道是否有可能根据变量从 target_sources() 中排除某些来源。

假设我在下面有这个

target_sources(myTarget
    PUBLIC
    PRIVATE
        myDir1/src/a.c
        myDir2/src/b.c
        myDir3/src/c.c      
    INTERFACE
)

target_include_directories(myTarget
    PUBLIC
    PRIVATE       
        myDir1/inc
        myDir2/inc
        myDir3/inc  
    INTERFACE
)

我想根据名为 myFlag 的标志从 myDir3 中排除/包含源/目录。我怎样才能做到这一点?

target_sources(myTarget
    PUBLIC
    PRIVATE
        myDir1/src/a.c
        myDir2/src/b.c
        if(DEFINED myFlag)
           myDir3/src/c.c
        endif()
    INTERFACE
)

target_include_directories(myTarget
    PUBLIC
    PRIVATE        
        myDir1/inc
        myDir2/inc
        if(DEFINED myFlag)
           myDir3/inc  
        endif()
    INTERFACE
)

【问题讨论】:

  • sooo if(DEFINED myFlag) target_sources(myTarget myDir3/src/c.c) endif()?将同一目录添加到 PUBLICPRIVATE 没有意义...
  • @KamilCuk 然后我将从公众中删除...
  • 这里你肯定不想要if(DEFINED myFlag)...如果myFlag 设置为OFF 怎么办?
  • 如果没有添加任何内容,包括PUBLICINTERFACE 是没有意义的

标签: cmake cmake-language cmakelists-options


【解决方案1】:

您不能将 if 语句放在命令的参数列表中。 target_* 命令不会覆盖,而是追加,因此最简单的解决方案如下:

target_sources(
  myTarget
  PRIVATE
    myDir1/src/a.c
    myDir2/src/b.c 
)
if (myFlag) 
  target_sources(myTarget PRIVATE myDir3/src/c.c)
endif ()

target_include_directories(
  myTarget
  PRIVATE
    myDir1/inc
    myDir2/inc
)
if (myFlag) 
  target_include_directories(myTarget PRIVATE myDir3/inc)
endif ()

另一个更具声明性的选项是使用生成器表达式,如下所示:

target_sources(
  myTarget
  PRIVATE
    myDir1/src/a.c
    myDir2/src/b.c
    $<$<BOOL:${myFlag}>:myDir3/src/c.c>
)

【讨论】:

  • 第一个问题,您放置的第二个选项,声明性选项,如果存在myFlag,这是否启用或禁用myDir3/src/c.c 的使用?
  • 如果 myFlag 评估结果为真(例如 1ONTRUE 等),它将被包含在内。
  • 谢谢!如果我想包含文件以防标志“myflag”为“0”、“False”或“OFF”,我该如何使用此选项?
  • $&lt;NOT:$&lt;BOOL:...&gt;&gt; 见:cmake.org/cmake/help/latest/manual/…
  • 看到区别了吗? $&lt;$&lt;NOT:$&lt;BOOL:${myFlag}&gt;&gt;:myDir3/src/c.c&gt;。如果您需要更多帮助,请提出新问题。
【解决方案2】:

根据您尝试这样做的原因,将它们保留为源文件也可能有意义(因此它们会显示在例如 Visual Studio 的目标视图中),但将它们标记为标头以便它们不会被编译:

if (NOT myFlag)
  set_source_files_properties(
      srcfile1.cpp
      srcfile2.cpp
    PROPERTIES
      HEADER_FILE_ONLY ON
  )
endif()

CMake 的 documentation 甚至为此推荐了此功能:

如果你有一些你不知何故的源文件,这很有用 预处理,然后通过添加这些预处理源 add_library() 或 add_executable()。通常,在 IDE 中,不会有 原始来源的参考,仅这些预处理 来源。因此,通过为所有原始源文件设置此属性 到 ON,然后调用 add_library() 或 add_executable() while 通过预处理源和原始源,或通过 使用 target_sources() 添加原始源文件就可以了 人们会期待什么,即原始源文件将是可见的 在 IDE 中,并且不会被构建。

【讨论】:

  • 在现代世界中,Visual Studio 可以直接打开 CMake 项目,这实际上是 首选 工作流程。所以几乎没有理由这样做。
  • @AlexReinking:我知道 Visual Studio 可以直接打开 CMake 项目,但如果这样做,它只会在目标视图中显示已添加到目标的文件。如果您不添加标题,它们将不会显示。同样,如果您只是有条件地将源文件添加到目标源,除非设置了标志,否则它将不会显示。其他 IDE 也是如此,例如 Qt Creator。而且我看不出IDE如何可靠地做一些不同的事情。毕竟,头文件可以从任何地方包含,IDE 应该如何确定将它们添加到哪个目标?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-15
  • 2015-03-15
  • 1970-01-01
相关资源
最近更新 更多