【问题标题】:Get all source files a target depends on in CMake获取目标在 CMake 中依赖的所有源文件
【发布时间】:2017-01-19 19:22:37
【问题描述】:

使用 CMake,我如何获取进入可执行目标的所有源文件的列表,包括该可执行文件所依赖的所有目标中的所有源?

我们在代码库中有一个模式,其中初始化调用程序由构建系统根据源树中的文件名和路径生成。所以我需要一个可执行目标所依赖的所有源文件的完整路径(或相对于源根目录)。

【问题讨论】:

  • 您可以使用SOURCES 目标属性,并且可以找到迭代依赖目标的here 代码示例。你能描述一下你到目前为止所做的尝试吗?
  • 我没有意识到我可以像这样迭代依赖的目标。我想我可以让它与 SOURCES 属性一起使用。
  • 我通过覆盖 CMake 函数编写了类似的东西,如果您有兴趣(作为起点)可以提供代码示例。这是我们在这里讨论的一些外部库 CMake 代码还是您想在自己的代码中使用它?
  • 那太好了。这仅与我们自己的代码有关,因此任何内容都可以访问。
  • 有一篇 2009 年的相关博文,但还是有点笨拙:agateau.com/2009/cmake-and-make-dist

标签: cmake


【解决方案1】:

这是我获取一个目标的链接依赖关系的一段代码:

function(target_link_libraries _target)
    set(_mode "PUBLIC")
    foreach(_arg IN LISTS ARGN)
        if (_arg MATCHES "INTERFACE|PUBLIC|PRIVATE|LINK_PRIVATE|LINK_PUBLIC|LINK_INTERFACE_LIBRARIES")
            set(_mode "${_arg}")
        else()
            if (NOT _arg MATCHES "debug|optimized|general")
                set_property(GLOBAL APPEND PROPERTY GlobalTargetDepends${_target} ${_arg})
            endif()
        endif()
    endforeach()
    _target_link_libraries(${_target} ${ARGN})
endfunction()

function(get_link_dependencies _target _listvar)
    set(_worklist ${${_listvar}})
    if (TARGET ${_target})
        list(APPEND _worklist ${_target})
        get_property(_dependencies GLOBAL PROPERTY GlobalTargetDepends${_target})
        foreach(_dependency IN LISTS _dependencies)
            if (NOT _dependency IN_LIST _worklist)
                get_link_dependencies(${_dependency} _worklist)
            endif()
        endforeach()
        set(${_listvar} "${_worklist}" PARENT_SCOPE)
    endif()
endfunction()

对于较旧的 CMake 版本(3.4 之前),您需要将 IN_LIST 检查替换为 list(FIND ...) 调用:

[...]
        list(FIND _worklist ${_dependency} _idx)
        if (${_idx} EQUAL -1)
            get_link_dependencies(${_dependency} _worklist)
        endif()
[...]

这是我用过的测试代码:

cmake_minimum_required(VERSION 3.4)

project(GetSources)

cmake_policy(SET CMP0057 NEW)

[... include functions posted above ...]

file(WRITE a.cc "")
add_library(A STATIC a.cc)

file(WRITE b.cc "")
add_library(B STATIC b.cc)

file(WRITE main.cc "int main() { return 0; }")
add_executable(${PROJECT_NAME} main.cc)

target_link_libraries(B A)
target_link_libraries(${PROJECT_NAME} B)

get_link_dependencies(${PROJECT_NAME} _deps)
foreach(_dep IN LISTS _deps)
    get_target_property(_srcs ${_dep} SOURCES)
    get_target_property(_src_dir ${_dep} SOURCE_DIR)
    foreach(_src IN LISTS _srcs)
        message("${_src_dir}/${_src}")
    endforeach()
endforeach()

参考文献

【讨论】:

  • 非常适合可执行目标。出于某种原因,当在第二个库目标上运行它时,我需要 cmake_policy(SET CMP0057 NEW) 以使 IN_LISTif 语句中工作。
  • @PetterKvalvaag 感谢您的提示。我实际上将IN_LIST 引入了此答案的代码,并且不了解策略CMP0057(我用于测试的CMake 3.4 不会引发警告/错误)。我已经相应地更新了我的答案并添加了我之前的变体(使用 CMake 版本 2.8 测试)。
  • 谢谢。在我的情况下,还需要下一个限制: get_target_property(TARGET_TYPE ${_dep} TYPE) if (NOT TARGET_TYPE STREQUAL "INTERFACE_LIBRARY")
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-08-22
  • 2016-09-04
  • 2021-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-01
相关资源
最近更新 更多