CMake中的LINK_LIBRARIES的递归列表 [英] Recursive list of LINK_LIBRARIES in CMake
问题描述
我想获取一个链接到CMake中特定目标的所有库的绝对路径列表,用于调用 如何检索所需的绝对路径列表? 演示: 输出: 您的愿望已经存在了一段时间,就我所知 - 还没有(如CMake 3.3.2)嵌入到 一些希望,因为这张票列出了几种可能的替代方法。但是在我测试这些对你的例子 注意:因为这仅适用于Lib-To-Lib依赖项has - for this test - changed your 会提供例如 但是这会在输出中保留生成器表达式,并且您需要添加到列表中所有取决于目标,所以没有好处。 我已经从如何使用cmake函数get_prerequisites和get_filename_component进行目标依赖关系安装?,但它显示 - 如模块文档中所述 - 它只列出了共享的库。 ListSharedLibDependencies.cmake 会在我的Windows机器上输出: 参考 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 Therefore, if I link another CMake target, e.g. For How can I retrieve the desired list of absolute paths? Demonstration: Output:
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 I got some hope because this ticket lists a few possible alternative approaches. But after I tested those against your example Note: Because this works only for Lib-To-Lib dependencies I have - for this test - changed your would give e.g. See also policy CMP0033 "The export_library_dependencies() command should not be called" But this keeps the generator expressions in the output and you need add to the list all depending targets, so no good. 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. ListSharedLibDependencies.cmake would output on my Windows machine: References 这篇关于CMake中的LINK_LIBRARIES的递归列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋! add_custom_command
。但是, get_target_property(_LINK_LIBRARIES $ {TARGET} LINK_LIBRARIES
仅包含直接依赖关系(即在 target_link_libraries($ {TARGET})中使用的任何内容。因此,如果我链接另一个CMake目标,例如
mylibrary
>,列表将包括 mylibrary
,但是作为一个名称,没有传递链接库,因为这个列表还可以包括任意复杂的生成器表达式,检查每个项目,如果它是一个目标并且递归地检索它的 LINK_LIBRARIES
是不可行的。此外,目标可以在 CMakeLists.txt
INCLUDE_DIRECTORIES $
c $ c>和
COMPILE_DEFINITIONS
这很容易解决,因为虽然两个行为类似,当使用 get_target_property
目标显然不在列表中),形式 $
$< TARGET_PROPERTY:$ {TARGET},LINK_LIBRARIES>
产生与 get_target_property
/ p>
cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR)
文件(WRITE a.cppvoid foo(){}; \\\
)
文件(WRITE b.cppint main(int,char **){return 0;} \\\
)
find_package(Boost REQUIRED COMPONENTS文件系统)
add_library(A STATIC a.cpp)
target_include_directories(A PUBLIC $ {Boost_INCLUDE_DIRS})
target_link_libraries(A PUBLIC $ {Boost_LIBRARIES})
#演示在配置时),LINK_LIBRARIES属性可以包含
#任意生成器表达式,使得递归解不可行
get_target_property(A_LINK_LIBRARIES A LINK_LIBRARIES)
消息(状态A LINK_LIBARIES:$ {A_LINK_LIBRARIES} )
add_executable(B b.cpp b_lists)
target_link_libraries(B PRIVATE A)
target_include_directories(B PRIVATE。)
get_target_property(B_INCLUDE_DIRECTORIES B INCLUDE_DIRECTORIES )
get_target_property(B_LINK_LIBRARIES B LINK_LIBRARIES)
#演示(在编译时)方法1不是递归的,而方法2是(对于INCLUDE_DIRECTORIES)
#演示)库列表从不递归
add_custom_command(
OUTPUT b_lists
COMMAND $ {CMAKE_COMMAND} -E echoB INCLUDE_DIRECTORIES 1:$ {B_INCLUDE_DIRECTORIES}
COMMAND $ {CMAKE_COMMAND } -E echoB INCLUDE_DIRECTORIES 2:$< TARGET_PROPERTY:B,INCLUDE_DIRECTORIES>
COMMAND $ {CMAKE_COMMAND} -E echoB LINK_LIBRARIES 1:$ {B_LINK_LIBRARIES}
COMMAND $ {CMAKE_COMMAND} -E echoB LINK_LIBRARIES 2:$< TARGET_PROPERTY:B,LINK_LIBRARIES>
DEPENDS A
)
set_source_files_properties(b_lists PROPERTIES SYMBOLIC TRUE)
$ b A LINK_LIBARIES:$< $< NOT:$< CONFIG:DEBUG>>::D:/libs/boost-1_55_0/lib/boost_filesystem-vc110-mt-1_55.lib> ;; $< $& ; CONFIG:DEBUG>:D:/libs/boost-1_55_0/lib/boost_filesystem-vc110-mt-gd-1_55.lib> ;; $< $< NOT:$< CONFIG:DEBUG>>:D: /libs/boost-1_55_0/lib/boost_system-vc110-mt-1_55.lib>;$<$<CONFIG:DEBUG>:D:/libs/boost-1_55_0/lib/boost_system-vc110-mt-gd- 1_55.lib>
(build)
生成b_lists
B INCLUDE_DIRECTORIES 1:D:/ projects / cmakeminimal /。
B INCLUDE_DIRECTORIES 2:D:/ projects / cmakeminimal / .; D:/ libs / boost-1_55_0 / include / boost-1_55
B LINK_LIBRARIES 1:A
B LINK_LIBRARIES 2:A
CMake
本身(参见 0012435:可以获取目标的所有链接库吗?)。
CMake
项目后,我会说他们不是一个真正的解决方案:
export_library_dependencies( )
- 已弃用
add_executable()
更改为 add_library()
调用
cmake_policy(SET CMP0033 OLD)
export_library_dependencies(LibToLibLinkDependencies.cmake)
include($ {CMAKE_CURRENT_BINARY_DIR} /LibToLibLinkDependencies.cmake)
消息(A_LIB_DEPENDS:$ {A_LIB_DEPENDS})
消息(B_LIB_DEPENDS:$ {B_LIB_DEPENDS})
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;
cmake_policy(SET CMP0024 OLD)
export(
TARGETS AB
FILE Test.cmake
NAMESPACE Imp_
)
include($ {CMAKE_CURRENT_BINARY_DIR} /Test.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
)
include(GetPrerequisites)
$ b get_prerequisites $ {MY_BINARY_LOCATION} DEPENDENCIES 0 0)
foreach(DEPENDENCY_FILE $ {DEPENDENCIES})
gp_resolve_item($ {MY_BINARY_LOCATION}$ {DEPENDENCY_FILE} resolved_file)
消息(resolved_file ='$ {resolved_file}')
endforeach()
resolved_file ='C:/Windows/SysWOW64/KERNEL32.dll'
resolved_file ='C:/Windows/SysWOW64/MSVCR110D.dll'
add_custom_command
. However, get_target_property(_LINK_LIBRARIES ${TARGET} LINK_LIBRARIES
only includes the direct dependencies (i.e. anything that is used in a target_link_libraries(${TARGET} ...)
call).mylibrary
, the list would include mylibrary
, but as a name only and without transitively linked libraries. As this list can also include arbitrarily complex generator expressions, checking each item if it is a target and retrieving its LINK_LIBRARIES
recursively is not viable. Furthermore the target could be specified at a later point in the CMakeLists.txt
and if(TARGET mylibrary)
would be skipped.INCLUDE_DIRECTORIES
and COMPILE_DEFINITIONS
this is easily solved, as although both behave similarly when get_target_property
is used (except that linked targets are obviously not in the list), a generator expression of the form $<TARGET_PROPERTY:${TARGET},INCLUDE_DIRECTORIES>
produces the desired list of recursively required includes and definitions. However, $<TARGET_PROPERTY:${TARGET},LINK_LIBRARIES>
produces the same list as the get_target_property
variant.cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR)
file(WRITE a.cpp "void foo() {};\n")
file(WRITE b.cpp "int main(int, char**) { return 0; }\n")
find_package(Boost REQUIRED COMPONENTS filesystem system)
add_library(A STATIC a.cpp)
target_include_directories(A PUBLIC ${Boost_INCLUDE_DIRS})
target_link_libraries(A PUBLIC ${Boost_LIBRARIES})
# demonstrates (at configure time) that the LINK_LIBRARIES property can contain
# arbitrary generator expressions, making a recursive solution infeasible
get_target_property(A_LINK_LIBRARIES A LINK_LIBRARIES)
message(STATUS "A LINK_LIBARIES: ${A_LINK_LIBRARIES}")
add_executable(B b.cpp b_lists)
target_link_libraries(B PRIVATE A)
target_include_directories(B PRIVATE .)
get_target_property(B_INCLUDE_DIRECTORIES B INCLUDE_DIRECTORIES)
get_target_property(B_LINK_LIBRARIES B LINK_LIBRARIES)
# demonstrates (at compile time) that method 1 is not recursive while method 2 is (for INCLUDE_DIRECTORIES)
# demonstrates (at compile time) that the library list is never recursive
add_custom_command(
OUTPUT b_lists
COMMAND ${CMAKE_COMMAND} -E echo "B INCLUDE_DIRECTORIES 1: ${B_INCLUDE_DIRECTORIES}"
COMMAND ${CMAKE_COMMAND} -E echo "B INCLUDE_DIRECTORIES 2: $<TARGET_PROPERTY:B,INCLUDE_DIRECTORIES>"
COMMAND ${CMAKE_COMMAND} -E echo "B LINK_LIBRARIES 1: ${B_LINK_LIBRARIES}"
COMMAND ${CMAKE_COMMAND} -E echo "B LINK_LIBRARIES 2: $<TARGET_PROPERTY:B,LINK_LIBRARIES>"
DEPENDS A
)
set_source_files_properties(b_lists PROPERTIES SYMBOLIC TRUE)
(configure)
A LINK_LIBARIES: $<$<NOT:$<CONFIG:DEBUG>>:D:/libs/boost-1_55_0/lib/boost_filesystem-vc110-mt-1_55.lib>;$<$<CONFIG:DEBUG>:D:/libs/boost-1_55_0/lib/boost_filesystem-vc110-mt-gd-1_55.lib>;$<$<NOT:$<CONFIG:DEBUG>>:D:/libs/boost-1_55_0/lib/boost_system-vc110-mt-1_55.lib>;$<$<CONFIG:DEBUG>:D:/libs/boost-1_55_0/lib/boost_system-vc110-mt-gd-1_55.lib>
(build)
Generating b_lists
B INCLUDE_DIRECTORIES 1: D:/projects/cmakeminimal/.
B INCLUDE_DIRECTORIES 2: D:/projects/cmakeminimal/.;D:/libs/boost-1_55_0/include/boost-1_55
B LINK_LIBRARIES 1: A
B LINK_LIBRARIES 2: A
CMake
itself (see 0012435: Possibility to get all link libraries for a target?).CMake
project I would say they are not really a solution:
export_library_dependencies()
- Deprecatedadd_executable()
to an add_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}")
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;
cmake_policy(SET CMP0024 OLD)
export(
TARGETS A B
FILE Test.cmake
NAMESPACE Imp_
)
include("${CMAKE_CURRENT_BINARY_DIR}/Test.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"
)
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()
resolved_file='C:/Windows/SysWOW64/KERNEL32.dll'
resolved_file='C:/Windows/SysWOW64/MSVCR110D.dll'