我可以在CMake中控制源与目标源的排除吗?

我可以在CMake中控制源与目标源的排除吗?,cmake,cmake-language,cmakelists-options,Cmake,Cmake Language,Cmakelists Options,我是CMake的新手,我想知道是否有可能基于变量从目标源中排除某些源 假设我在下面有这个 target_sources(myTarget PUBLIC PRIVATE myDir1/src/a.c myDir2/src/b.c myDir3/src/c.c INTERFACE ) target_include_directories(myTarget PUBLIC PRIVATE

我是CMake的新手,我想知道是否有可能基于变量从目标源中排除某些源

假设我在下面有这个

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
)

不能将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>
)

不能将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>
)

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

if (NOT myFlag)
  set_source_files_properties(
      srcfile1.cpp
      srcfile2.cpp
    PROPERTIES
      HEADER_FILE_ONLY ON
  )
endif()
为此,CMake公司甚至建议:

如果您有一些源文件,但不知何故 预处理,然后通过 添加\u库或添加\u可执行文件。通常,在IDE中,没有 原始来源的参考,仅这些预处理 来源。因此,通过为所有原始源文件设置此属性 打开,然后调用add_library或add_executable,同时 传递预处理源和原始源,或通过 使用目标_源添加原始源文件正好可以 人们会期望什么,即原始源文件是可见的 在IDE中,将不会生成


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

if (NOT myFlag)
  set_source_files_properties(
      srcfile1.cpp
      srcfile2.cpp
    PROPERTIES
      HEADER_FILE_ONLY ON
  )
endif()
为此,CMake公司甚至建议:

如果您有一些源文件,但不知何故 预处理,然后通过 添加\u库或添加\u可执行文件。通常,在IDE中,没有 原始来源的参考,仅这些预处理 来源。因此,通过为所有原始源文件设置此属性 打开,然后调用add_library或add_executable,同时 传递预处理源和原始源,或通过 使用目标_源添加原始源文件正好可以 人们会期望什么,即原始源文件是可见的 在IDE中,将不会生成


sooo如果定义了myFlag目标\u sourcesmyTarget myDir3/src/c.c endif?在公共和私有目录中添加相同的目录是没有意义的…@KamilCuk我将从公共目录中删除…您肯定不希望在此处定义ifDEFINED myFlag。。。如果myFlag设置为OFF怎么办?如果没有任何内容添加到PUBLIC或INTERFACE,那么就没有必要包含它们。如果定义了myFlag target\u sourcesmyTarget myDir3/src/c.c endif?在公共和私有目录中添加相同的目录是没有意义的…@KamilCuk我将从公共目录中删除…您肯定不希望在此处定义ifDEFINED myFlag。。。如果myFlag设置为OFF怎么办?在现代世界中,如果不向其添加任何内容,则没有必要包括PUBLIC或INTERFACE。Visual Studio可以直接打开CMake项目,而这实际上是首选工作流。所以没有什么理由这么做。@AlexReinking:我知道Visual Studio可以直接打开CMake项目,但如果这样做,它将只在“目标”视图中显示已添加到目标的文件。如果不添加标题,它们将不会显示。类似地,如果仅有条件地将源文件添加到目标源,则除非设置了该标志,否则不会显示该源文件。其他IDE也是如此,比如QtCreator。我看不出IDE有什么方法可以可靠地做一些不同的事情。毕竟,可以从任何地方包含标题,IDE应该如何确定要将标题添加到哪个目标?在现代世界中,Visual Studio可以直接打开CMake项目,这实际上是首选工作流。所以没有什么理由这么做。@AlexReinking:我知道Visual Studio可以直接打开CMake项目,但如果这样做,它将只在“目标”视图中显示已添加到目标的文件。如果不添加标题,它们将不会显示。类似地,如果仅有条件地将源文件添加到目标源,则除非设置了该标志,否则不会显示该源文件。其他IDE也是如此,比如QtCreator。我看不出IDE有什么方法可以可靠地做一些不同的事情。毕竟,头可以从任何地方包含,IDE应该如何确定将它们添加到哪个目标?一个问题,即您放置的第二个选项,声明性选项,如果存在myFlag,这是否启用或禁用myDir3/src/c.c的使用?如果myFlag的计算结果为s
如1、ON、true等,将包括在内。谢谢!如果我希望在标记“myflag”为“0”、“False”或“OFF”的情况下包含该文件,如何使用此选项?$请参阅:查看差异?$。如果您需要更多帮助,请提出一个新问题。一个问题,即您放置的第二个选项,声明性选项,如果存在myFlag,这是否启用或禁用myDir3/src/c.c的使用?如果myFlag的计算结果为真,例如1、ON、true等,则将包括在内。谢谢!如果我希望在标记“myflag”为“0”、“False”或“OFF”的情况下包含该文件,如何使用此选项?$请参阅:查看差异?$。如果你需要更多的帮助,请问一个新问题。