【问题标题】:How do I iterate over all CMake targets programmatically?如何以编程方式迭代所有 CMake 目标?
【发布时间】:2016-05-25 10:52:32
【问题描述】:

有没有办法从顶层 CMakeLists.txt 中获取 CMake 项目的所有目标,即以编程方式迭代目标?

我想这样做的原因是对每个目标应用一些 XCode 特定设置。 .

if (CMAKE_GENERATOR MATCHES "Xcode")
    include(sanitize_xcode)
    sanitize_xcode(myTarget)
endif()

仅供参考 - 清理模块看起来像这样。 .

macro (set_xcode_property TARGET XCODE_PROPERTY XCODE_VALUE)
    set_property (TARGET ${TARGET} PROPERTY XCODE_ATTRIBUTE_${XCODE_PROPERTY} ${XCODE_VALUE})
endmacro (set_xcode_property)

macro (sanitize_xcode TARGET)
    set_xcode_property(${TARGET} GCC_GENERATE_DEBUGGING_SYMBOLS[variant=Debug] "YES")
    set_xcode_property(${TARGET} GCC_GENERATE_DEBUGGING_SYMBOLS[variant=MinSizeRel] "NO")
    set_xcode_property(${TARGET} GCC_GENERATE_DEBUGGING_SYMBOLS[variant=RelWithDebInfo] "YES")
    set_xcode_property(${TARGET} GCC_GENERATE_DEBUGGING_SYMBOLS[variant=Release] "NO")

    set_xcode_property(${TARGET} COPY_PHASE_STRIP[variant=Debug] "NO")
    set_xcode_property(${TARGET} COPY_PHASE_STRIP[variant=MinSizeRel] "YES")
    set_xcode_property(${TARGET} COPY_PHASE_STRIP[variant=RelWithDebInfo] "NO")
    set_xcode_property(${TARGET} COPY_PHASE_STRIP[variant=Release] "YES")

    set_xcode_property(${TARGET} GCC_OPTIMIZATION_LEVEL[variant=Debug] "0")
    set_xcode_property(${TARGET} GCC_OPTIMIZATION_LEVEL[variant=MinSizeRel] "s")
    set_xcode_property(${TARGET} GCC_OPTIMIZATION_LEVEL[variant=RelWithDebInfo] "3")
    set_xcode_property(${TARGET} GCC_OPTIMIZATION_LEVEL[variant=Release] "3")

    set_xcode_property(${TARGET} IPHONEOS_DEPLOYMENT_TARGET[variant=Debug] "7.0")
    set_xcode_property(${TARGET} IPHONEOS_DEPLOYMENT_TARGET[variant=MinSizeRel] "7.0")
    set_xcode_property(${TARGET} IPHONEOS_DEPLOYMENT_TARGET[variant=RelWithDebInfo] "7.0")
    set_xcode_property(${TARGET} IPHONEOS_DEPLOYMENT_TARGET[variant=Release] "7.0")
endmacro (sanitize_xcode)

【问题讨论】:

  • 您的意思是以编程方式迭代您的 cmake 脚本中的目标吗?
  • 有什么目的? (闻到 X-Y 问题。)无论您想做什么,最好在 CMakeLists.txt 本身中完成。
  • @DevSolar 查看编辑。
  • 能否请您也提供sanitize_xcode() 的代码?您添加POST_BUILD 步骤还是仅添加编译器选项?如果是后者,则不需要遍历所有目标。
  • 谢谢。仅查看XCODE_ATTRIBUTE_<an-attribute> 目标属性是否足以在根级别设置等效的CMAKE_XCODE_ATTRIBUTE_<an-attribute> 变量以应用于所有目标?

标签: c++ c cmake target


【解决方案1】:

为了更正 Florian 的 answerBUILDSYSTEM_TARGETS 并不是真正的全局属性,而是directory 范围的属性。目前的增强请求是open,以请求真正的全局属性。使用SUBDIRECTORIES 属性,可以使用以下函数递归检索当前目录范围内的所有目标:

function(get_all_targets var)
    set(targets)
    get_all_targets_recursive(targets ${CMAKE_CURRENT_SOURCE_DIR})
    set(${var} ${targets} PARENT_SCOPE)
endfunction()

macro(get_all_targets_recursive targets dir)
    get_property(subdirectories DIRECTORY ${dir} PROPERTY SUBDIRECTORIES)
    foreach(subdir ${subdirectories})
        get_all_targets_recursive(${targets} ${subdir})
    endforeach()

    get_property(current_targets DIRECTORY ${dir} PROPERTY BUILDSYSTEM_TARGETS)
    list(APPEND ${targets} ${current_targets})
endmacro()

get_all_targets(all_targets)
message("All targets: ${all_targets}")

【讨论】:

  • 天哪,我爱你,这解决了一个困扰我一整天的问题。 +1
  • 这太棒了,我一直想要一种方法来做到这一点,但基本上放弃了
  • 应该注意的是,这个解决方案将生成一个真正的 all 目标列表,包括那些已经明确排除在“all”之外的目标:add_executable(some_target EXCLUDE_FROM_ALL some_target.c) 这真的很有用用于添加将构建真正所有的目标,甚至包括排除的目标:add_custom_target(really_all DEPENDS ${all_targets})
【解决方案2】:

把我的评论变成答案

拥有所有目标的列表是一个已经存在一段时间的愿望,但尚未实现全局属性TARGETS(至于 2016 年 5 月,see "Listing all targets" discussion)。

编辑:现在实现了:全局BUILDSYSTEM_TARGETS属性随CMake 3.7发布

因此,您可以使用 CMake 脚本本身来实现这一点 - 就像评论/回答的 @DevSolar 或 here - 但我在使用 CMake 的过程中了解到,您还可以在全球范围内更改许多目标属性。例如。大多数目标属性默认为等效的全局变量设置。

您可以在您的情况下利用这一点,并通过将以下内容添加到您的全局 CMakeLists.txt 文件中来解决此问题:

set(CMAKE_XCODE_ATTRIBUTE_GCC_GENERATE_DEBUGGING_SYMBOLS[variant=Debug] "YES")
set(CMAKE_XCODE_ATTRIBUTE_GCC_GENERATE_DEBUGGING_SYMBOLS[variant=MinSizeRel] "NO")
set(CMAKE_XCODE_ATTRIBUTE_GCC_GENERATE_DEBUGGING_SYMBOLS[variant=RelWithDebInfo] "YES")
set(CMAKE_XCODE_ATTRIBUTE_GCC_GENERATE_DEBUGGING_SYMBOLS[variant=Release] "NO")

set(CMAKE_XCODE_ATTRIBUTE_COPY_PHASE_STRIP[variant=Debug] "NO")
set(CMAKE_XCODE_ATTRIBUTE_COPY_PHASE_STRIP[variant=MinSizeRel] "YES")
set(CMAKE_XCODE_ATTRIBUTE_COPY_PHASE_STRIP[variant=RelWithDebInfo] "NO")
set(CMAKE_XCODE_ATTRIBUTE_COPY_PHASE_STRIP[variant=Release] "YES")

set(CMAKE_XCODE_ATTRIBUTE_GCC_OPTIMIZATION_LEVEL[variant=Debug] "0")
set(CMAKE_XCODE_ATTRIBUTE_GCC_OPTIMIZATION_LEVEL[variant=MinSizeRel] "s")
set(CMAKE_XCODE_ATTRIBUTE_GCC_OPTIMIZATION_LEVEL[variant=RelWithDebInfo] "3")
set(CMAKE_XCODE_ATTRIBUTE_GCC_OPTIMIZATION_LEVEL[variant=Release] "3")

set(CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET[variant=Debug] "7.0")
set(CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET[variant=MinSizeRel] "7.0")
set(CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET[variant=RelWithDebInfo] "7.0")
set(CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET[variant=Release] "7.0")

参考文献

【讨论】:

  • 不,全局BUILDSYSTEM_TARGETS 没有被添加,它是一个目录属性。有一个rfe
  • 使用BUILDSYSTEM_TARGETSSUBDIRECTORIES 可以递归地检索在当前目录范围内定义的目标。见我的answer
【解决方案3】:

如果您想查看目标列表,请将您的 CMakeLists.txt 设置为首先提供该列表。

if ( CMAKE_GENERATOR MATCHES "Xcode" )
    include(sanitize_xcode)
endif()

# A list of executables to build
set( project_EXECUTABLES
     foo
     bar
   )

# List of sources for each executable, following some naming scheme

# foo
set( EXE_foo_SOURCES
     foo/main.c
   )

# bar
set( EXE_bar_SOURCES
     bar/main.c
   )

# For each executable in the list...
foreach( exe ${project_EXECUTABLES} )
    # declare the target...
    add_executable( ${exe} ${EXE_${exe}_SOURCES} )

    # ...and do whatever additional configuration you need
    if ( CMAKE_GENERATOR MATCHES "Xcode" )
        sanitize_xcode( ${exe} )
    endif()
endforeach()

【讨论】:

  • 我发现在开始时有一系列set() 命令通常是一个好技巧,设置好所有东西,最后做所有的“魔术”。实际上,in my re-useable CMake framework,我在我的CMakeLists.txt 中执行set()s,然后在include() 一个包含所有“魔法”的文件中执行。如果我添加/更改源文件,我只会“触摸”CMakeLists.txt,如果我修改“魔法”,我会“触摸”另一个文件。更容易维护,恕我直言。
  • 这不是答案,因为目标列表可能只是未知/不可预测。
  • @ceztko: 1) 如果您的目标列表不可预测,那么您还有其他问题。 2) 答案显示了一种方法来设置目标列表以进行迭代。 3) BUILDSYSTEM_TARGETS 是在我和 Florian 写我们的(初始)答案半年后 引入的,所以你很难怪我们在写答案时没有使用它。当时,这些问题的答案。后来出现的更好的机制可能会使这个答案有点过时,但“不是答案”是不必要的。
  • @ceztko:哦,我想我现在明白了。您在 subdirectories 中也有 CMakeLists.txt,这就是为什么您认为目标列表是“未知/不可预测”的?好吧,我不这样做,来自“递归制造被认为有害”的思想流派,只有一个顶级 CMakeLists.txt。所以我们在这里根据不同的假设工作。
猜你喜欢
  • 1970-01-01
  • 2015-05-28
  • 1970-01-01
  • 2015-07-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-12
  • 2011-04-17
  • 2023-03-24
相关资源
最近更新 更多