CMake中LINK_LIBRARIES的递归列表

时间:2015-09-24 07:57:12

标签: cmake

我正在尝试获取链接到CMake中特定目标的所有库的绝对路径列表,以便在调用em时使用。但是,.main { width:378px; height:250px; } 仅包含直接依赖项(即table.setIntercellSpacing(new Dimension(0, 0))调用中使用的任何内容)。

因此,如果我链接另一个CMake目标,例如add_custom_command,列表将包含get_target_property(_LINK_LIBRARIES ${TARGET} LINK_LIBRARIES,但仅作为名称,不包含可传递链接的库。由于此列表还可以包含任意复杂的生成器表达式,因此检查每个项目是否为目标并以递归方式检索其target_link_libraries(${TARGET} ...)是不可行的。此外,可以在mylibrary稍后指定目标,并跳过mylibrary

对于LINK_LIBRARIESCMakeLists.txt,这很容易解决,因为虽然使用if(TARGET mylibrary)时两者的行为相似(除了链接目标显然不在列表中),但生成器表达式为形式INCLUDE_DIRECTORIES生成所需的递归必需包含和定义列表。但是,COMPILE_DEFINITIONS会生成与get_target_property变体相同的列表。

如何检索所需的绝对路径列表?

演示:

$<TARGET_PROPERTY:${TARGET},INCLUDE_DIRECTORIES>

输出:

$<TARGET_PROPERTY:${TARGET},LINK_LIBRARIES>

2 个答案:

答案 0 :(得分:7)

你的愿望已经存在了一段时间,而且 - 据我所知 - 尚未(至于CMake 3.3.2)嵌入clinic.menu.item_set.all()本身(见0012435: Possibility to get all link libraries for a target?)。

我有一些希望,因为这张票列出了一些可能的替代方法。但是在我针对您的示例CMake项目测试了这些后,我会说它们不是真正的解决方案:

  1. export_library_dependencies() - 已弃用

    注意:因为这仅适用于Lib-To-Lib依赖项,所以我对此测试将CMake更改为add_executable()调用

    add_library()

    会给出例如。

    cmake_policy(SET CMP0033 OLD)
    export_library_dependencies(LibToLibLinkDependencies.cmake)
    include("${CMAKE_CURRENT_BINARY_DIR}/LibToLibLinkDependencies.cmake")
    
    message("A_LIB_DEPENDS: ${A_LIB_DEPENDS}")
    message("B_LIB_DEPENDS: ${B_LIB_DEPENDS}")
    

    另见policy CMP0033 "The export_library_dependencies() command should not be called"

  2. export(TARGETS ...)

    A_LIB_DEPENDS: optimized;../libboost_filesystem-vc110-mt-1_53.lib;debug;../libboost_filesystem-vc110-mt-gd-1_53.lib;...
    B_LIB_DEPENDS: general;A;
    

    但这会将生成器表达式保留在输出中,您需要将所有依赖目标添加到列表中,所以没有好处。

    另见policy CMP0024 "Disallow include export result"

  3. GET_PREREQUISITES()

    我从how to use the cmake functions get_prerequisites and get_filename_component for target dependency installation?获取了代码,但它显示了 - 如模块文档中所述 - 它只列出共享库。

    cmake_policy(SET CMP0024 OLD)
    export(
        TARGETS A B
        FILE Test.cmake 
        NAMESPACE Imp_
    )
    include("${CMAKE_CURRENT_BINARY_DIR}/Test.cmake")
    

    <强> ListSharedLibDependencies.cmake

    add_custom_command(
        OUTPUT b_lists
        APPEND
        COMMAND ${CMAKE_COMMAND} -D MY_BINARY_LOCATION="$<TARGET_FILE:B>" -P "${CMAKE_CURRENT_LIST_DIR}/ListSharedLibDependencies.cmake"
    )
    

    将在我的Windows机器上输出:

    include(GetPrerequisites)
    
    get_prerequisites(${MY_BINARY_LOCATION} DEPENDENCIES 0 0 "" "")
    
    foreach(DEPENDENCY_FILE ${DEPENDENCIES})
        gp_resolve_item("${MY_BINARY_LOCATION}" "${DEPENDENCY_FILE}" "" "" resolved_file)
        message("resolved_file='${resolved_file}'")
    endforeach()
    
  4. <强>参考

答案 1 :(得分:4)

可以递归遍历LINK_LIBRARY属性。

这是get_link_libraries()这样做,但它不处理所有情况(例如,库不是目标,而不是导入的库)。

function(get_link_libraries OUTPUT_LIST TARGET)
    get_target_property(IMPORTED ${TARGET} IMPORTED)
    list(APPEND VISITED_TARGETS ${TARGET})
    if (IMPORTED)
        get_target_property(LIBS ${TARGET} INTERFACE_LINK_LIBRARIES)
    else()
        get_target_property(LIBS ${TARGET} LINK_LIBRARIES)
    endif()
    set(LIB_FILES "")
    foreach(LIB ${LIBS})
        if (TARGET ${LIB})
            list(FIND VISITED_TARGETS ${LIB} VISITED)
            if (${VISITED} EQUAL -1)
                get_target_property(LIB_FILE ${LIB} LOCATION)
                get_link_libraries(LINK_LIB_FILES ${LIB})
                list(APPEND LIB_FILES ${LIB_FILE} ${LINK_LIB_FILES})
            endif()
        endif()
    endforeach()
    set(VISITED_TARGETS ${VISITED_TARGETS} PARENT_SCOPE)
    set(${OUTPUT_LIST} ${LIB_FILES} PARENT_SCOPE)
endfunction()