我有一个使用 CMake 构建的静态库。该库依赖于其他几个库,为了减轻另一个团队的工作负担,我们在将产品交付给他们之前将所有静态库合并为一个(由于某些原因,我们决定将我们的产品作为静态库而不是动态库交付,并且我无法改变这一点)。
截至今天,我们手动收集了依赖项列表并编写了一个调用存档器的脚本,但是我认为这可以由 cmake 自动完成,所以我尝试了一下。
我设法提取了修改这个答案的依赖项列表,但我不太确定如何将其转换为我可以提供给 ar/libtool 的路径列表。 这是我上次尝试的代码。从输出来看,所有参数都作为唯一的带引号的字符串传递给 libtool。
function(get_dependencies TARGET)
get_target_property(target_type ${TARGET} TYPE)
if (NOT target_type STREQUAL "STATIC_LIBRARY")
return()
endif()
get_target_property(IMPORTED ${TARGET} IMPORTED)
list(APPEND TARGET_DEPENDENCIES ${TARGET})
if (IMPORTED)
get_target_property(LIBS ${TARGET} INTERFACE_LINK_LIBRARIES)
else()
get_target_property(LIBS ${TARGET} LINK_LIBRARIES)
endif()
foreach(LIB ${LIBS})
if (TARGET ${LIB})
list(FIND TARGET_DEPENDENCIES ${LIB} VISITED)
if (${VISITED} EQUAL -1)
get_dependencies(${LIB})
endif()
endif()
endforeach()
set(TARGET_DEPENDENCIES ${TARGET_DEPENDENCIES} PARENT_SCOPE)
endfunction()
function(merge_libraries target destination)
get_dependencies(${target})
list(TRANSFORM TARGET_DEPENDENCIES PREPEND "$<TARGET_FILE:")
list(TRANSFORM TARGET_DEPENDENCIES APPEND ">")
add_custom_target(Merge${target}Libraries
COMMAND libtool -static -o ${destination} "$<GENEX_EVAL:$<JOIN:${TARGET_DEPENDENCIES}, >>"
COMMAND_EXPAND_LISTS
DEPENDS ${target})
endfunction()
输出:
error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool: can't open file: /path/to/lib1.a /path/to/lib2.a /path/to/lib3.a ... (File name too long)
编辑: 为我们的约束添加上下文:我们正在构建的库稍后将由一些 C# 和 Swift 应用程序链接。 AFAIK 我们可以在 C# 中使用 cmake 和动态库,但是 Swift/C++ 互操作需要嵌入在 xcframework 中的静态库,这就是我们需要将其构建为静态库的原因。
正如评论中已经指出的,依赖项是使用 cmake FetchContent 模块与我们的库一起构建的 c++ 项目。
事实证明我几乎是对的,但是自定义目标中的生成器表达式存在问题。 正如here所建议的,我必须用
$<SEMICOLON>
更改空白
所以add_custom_target就变成了
add_custom_target(Merge${target}Libraries
COMMAND libtool -static -o ${destination} "$<GENEX_EVAL:$<JOIN:${TARGET_DEPENDENCIES},$<SEMICOLON>>>"
COMMAND_EXPAND_LISTS
DEPENDS ${target})