Recursive list of LINK_LIBRARIES in CMake

后端 未结 2 1066
名媛妹妹
名媛妹妹 2020-11-28 10:00

I am trying to acquire a list of the absolute paths to all libraries linked to a specific target in CMake for use in a call to add_custom_command. However,

相关标签:
2条回答
  • 2020-11-28 10:51

    Your wish has been out there for a while and is - as far as I know - not yet (as for CMake 3.3.2) embedded into CMake itself (see 0012435: Possibility to get all link libraries for a target?).

    I got some hope because this ticket lists a few possible alternative approaches. But after I tested those against your example CMake project I would say they are not really a solution:

    1. export_library_dependencies() - Deprecated

      Note: Because this works only for Lib-To-Lib dependencies I have - for this test - changed your add_executable() to an add_library() call

      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}")
      

      would give e.g.

      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;
      

      See also policy CMP0033 "The export_library_dependencies() command should not be called"

    2. export(TARGETS ...)

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

      But this keeps the generator expressions in the output and you need add to the list all depending targets, so no good.

      See also policy CMP0024 "Disallow include export result".

    3. GET_PREREQUISITES()

      I've taken the code from how to use the cmake functions get_prerequisites and get_filename_component for target dependency installation?, but it shows - as described in the module's documentation - that it lists only the shared libraries.

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

      ListSharedLibDependencies.cmake

      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()
      

      would output on my Windows machine:

      resolved_file='C:/Windows/SysWOW64/KERNEL32.dll'
      resolved_file='C:/Windows/SysWOW64/MSVCR110D.dll'
      

    References

    • Retrieve all link flags in CMake
    • Get all source files a target depends on in CMake
    0 讨论(0)
  • 2020-11-28 10:52

    Recursively traversing LINK_LIBRARY property is possible.

    Here is a get_link_libraries() that does that, however it does not handle all cases (e.g. libraries not being a target, not imported 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()
    
    0 讨论(0)
提交回复
热议问题