Я пытаюсь получить список абсолютных путей ко всем библиотекам, связанным с определенной целью в CMake для использования при вызове add_custom_command
. Однако get_target_property(_LINK_LIBRARIES ${TARGET} LINK_LIBRARIES
включает только прямые зависимости (т.е. Все, что используется при вызове target_link_libraries(${TARGET} ...)
).
Поэтому, если я связываю другую цель CMake, например. mylibrary
, список будет включать mylibrary
, но как имя и без транзитно связанных библиотек. Поскольку этот список может также включать произвольно сложные выражения генератора, проверка каждого элемента, если он является целью и получение рекурсивно его LINK_LIBRARIES
, не является жизнеспособным. Кроме того, цель может быть указана в более поздней точке CMakeLists.txt
и if(TARGET mylibrary)
будет пропущена.
Для INCLUDE_DIRECTORIES
и COMPILE_DEFINITIONS
это легко решается, так как оба они ведут себя одинаково, когда используется get_target_property
(за исключением того, что связанные цели, очевидно, не входят в список), выражение генератора формы $<TARGET_PROPERTY:${TARGET},INCLUDE_DIRECTORIES>
производит требуемый список рекурсивно необходимых включает и определений. Однако $<TARGET_PROPERTY:${TARGET},LINK_LIBRARIES>
создает тот же список, что и вариант get_target_property
.
Как получить желаемый список абсолютных путей?
Демонстрация:
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