我正在构建一个依赖于由相当多的库组成的第三方库的项目。这些库之间的依赖关系的DAG是明确定义的,例如它可能是以下字母表示库和箭头是依赖关系
x -> a, b
y -> a, c
z -> x, b // note I don't need to specify a here as it is implied by x
所以我真正想要的是能够在CMake中表达这个DAG并且能够在不重复的情况下扩展依赖性。所以
Expand( y, z ) -> y, z, x, a, b, c // Note only one a
我会尽力避免尝试扩展功能,因为我无法想出任何优雅的东西,我对CMake并不擅长。
额外的功能是检测顶级依赖关系中的冗余,以便
Expand( z, x ) // x not needed as z depends on it
注意CMake已经为内部项目库依赖项执行了类似的操作,并在target_link_libraries之类的内容中使用它,但这些是外部的,因此CMake不知道外部依赖树。
答案 0 :(得分:0)
据我从CMake文档中了解,target_link_libraries
不能将导入的库作为第一个参数。但是您可以轻松地开发函数,该函数从依赖(导入)库中读取属性,并为依赖(导入)库填充相应的属性。因此,导出的导入库可以与右侧的target_link_libraries
一起使用。
# _combine_targets_property(VAR PROP target1 target2 ...)
# Helper function: Collects @PROP properties (as lists) from @target1, @target2 ..,
# combines these lists into one and store into variable @VAR.
function(_combine_targets_property VAR PROP)
set(values) # Resulted list
foreach(t ${ARGN})
get_property(v TARGET ${t} PROPERTY ${PROP})
list(APPEND values ${v})
endforeach()
set(${VAR} ${values} PARENT_SCOPE)
endfunction()
# imported_link_libraries(t_dest target1 target2 ...)
# Make imported library target @t_dest effectively linked with @target1, @target2 ...
function(imported_link_libraries t_dest)
# IMPORTED_LOCATION's and INTERFACE_LINK_LIBRARIES's from dependencies
# should be appended to target's INTERFACE_LINK_LIBRARIES.
get_property(v1 TARGET ${t_dest} PROPERTY INTERFACE_LINK_LIBRARIES)
_combine_targets_property(v2 IMPORTED_LOCATION ${ARGN})
_combine_targets_property(v3 INTERFACE_LINK_LIBRARIES ${ARGN})
set(v ${v1} ${v2} ${v3})
list(REMOVE_DUPLICATES v)
set_property(TARGET ${t_dest} PROPERTY INTERFACE_LINK_LIBRARIES ${v})
# INTERFACE_INCLUDE_DIRECTORIES' from dependencies
# should be appended to corresponded target's property.
get_property(v1 TARGET ${t_dest} PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
_combine_targets_property(v2 INTERFACE_INCLUDE_DIRECTORIES ${ARGN})
set(v ${v1} ${v2})
list(REMOVE_DUPLICATES v)
set_property(TARGET ${t_dest} PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${v})
# Process other interface properties if needed. E.g., INTERFACE_COMPILE_DEFINITIONS.
...
endfunction()
用法示例:
add_library(a IMPORTED)
set_target_properties(a IMPORTED_LOCATION <a_lib> INCLUDE_DIRECTORIES <a_include_dirs>)
add_library(b IMPORTED)
set_target_properties(b IMPORTED_LOCATION <b_lib> INCLUDE_DIRECTORIES <b_include_dirs>)
add_library(x IMPORTED)
set_target_properties(x IMPORTED_LOCATION <x_lib> INCLUDE_DIRECTORIES <x_include_dirs>)
imported_link_libraries(x a b)
add_executable(my_exec ...)
target_link_libraries(my_exec x)
请注意,导入的目标名称不会在依赖项中跟踪,这类似于target_link_libraries()
行为。此外,未检测到还原(但会自动删除重复项)。这两个功能对于CMake来说并不自然,但如果需要,可以实现它们。