CMake:打印目标的属性,包括其依赖项



我目前正在尝试编写一个custom_target来打印目标的属性(例如COMPILE_DEFINITIONS(。我几乎在Top-Level-CMakeLists.txt的末尾调用了这个custom_target创建,以确保所有模块都已被调用。

目标是打印出目标的所有属性,包括通过target_link_libraries由依赖项提供的属性。

简化示例:

add_library(libA STATIC)
add_library(libB STATIC)
target_compile_definitions(libA 
PRIVATE
PRIV_A
PUBLIC
PUB_A
INTERFACE
INT_A
)
target_compile_definitions(libB 
PRIVATE
PRIV_B
PUBLIC
PUB_B
INTERFACE
INT_B
)
# create dependency from A -> B, 
# this should compile A with all PUBLIC and INTERFACE defintions from B
target_link_libraries(libA libB)
get_target_property(compile_defs libA COMPILE_DEFINITIONS)
get_target_property(compile_defs_intf libA INTERFACE_COMPILE_DEFINITIONS)
message("compile_defs: ${compile_defs}")
message("compile_defs_intf: ${compile_defs_intf}")

这将打印:

compile_defs: PRIV_A; PUB_A
compile_defs_intf: PUB_A; INT_A

事实上,我想得到:

compile_defs: PRIV_A; PUB_A; PUB_B; INT_B

但很明显,在这个阶段,依赖关系还没有被解析/包含在属性中。一个可能的解决方法是迭代目标A的所有依赖项,并收集依赖项目标的所有INTERFACE_PROPERTIES。但这需要一些安静的递归来解决树中的所有依赖关系(例如,需要解决所有依赖关系…(

是否可以以更简单的方式获取目标的属性,包括其依赖项(PUBLIC、INTERFACE属性(?

首先获取所有依赖库:

# target_get_linked_libraries.cmake
# 
function(list_add_if_not_present list elem)
list(FIND "${list}" "${elem}" exists)
if(exists EQUAL -1)
list(APPEND "${list}" "${elem}")
set("${list}" "${${list}}" PARENT_SCOPE)
endif()
endfunction()
macro(_target_get_linked_libraries_in _target _outlist)
list_add_if_not_present("${_outlist}" "${_target}")
# get libraries
get_target_property(target_type "${_target}" TYPE)
if (${target_type} STREQUAL "INTERFACE_LIBRARY")
get_target_property(libs "${_target}" INTERFACE_LINK_LIBRARIES)
else()
get_target_property(libs "${_target}" LINK_LIBRARIES)
endif()
foreach(lib IN LISTS libs)
if(NOT TARGET "${lib}")
continue()
endif()

list(FIND "${_outlist}" "${lib}" exists)
if(NOT exists EQUAL -1)
continue()
endif()

_target_get_linked_libraries_in("${lib}" "${_outlist}")

endforeach()
endmacro()
function(target_get_linked_libraries _target _outlist)
set(${_outlist} "${_target}")
_target_get_linked_libraries_in(${_target} ${_outlist})
set(${_outlist} ${${_outlist}} PARENT_SCOPE) 
endfunction()

然后只需遍历所有依赖库并获得接口定义:

cmake_minimum_required(VERSION 3.11)
project(A)
add_library(libB STATIC)
target_compile_definitions(libB 
PRIVATE PRIV_B
PUBLIC PUB_B
INTERFACE INT_B
)
add_library(libA STATIC)
target_compile_definitions(libA 
PRIVATE PRIV_A
PUBLIC PUB_A
INTERFACE INT_A
)
target_link_libraries(libA PUBLIC libB)
include(target_get_linked_libraries.cmake)
target_get_linked_libraries(libA libraries)
set(compile_defs)
foreach(i IN LISTS libraries)
if("${i}" STREQUAL libA)
get_target_property(tmp "${i}" COMPILE_DEFINITIONS)
else()
get_target_property(tmp "${i}" INTERFACE_COMPILE_DEFINITIONS)
endif()
list(APPEND compile_defs "${tmp}")
endforeach()
message("compile_defs: ${compile_defs}")
message(FATAL_ERROR "")

将输出:

$ cmake .
compile_defs: PRIV_A;PUB_A;PUB_B;INT_B

相关内容

最新更新