Recursive list of LINK_LIBRARIES in CMake
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:
-
export_library_dependencies()
- DeprecatedNote: Because this works only for Lib-To-Lib dependencies I have - for this test - changed your
add_executable()
to anadd_library()
callcmake_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"
-
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".
-
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
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()