CMake - 如何使用 TARGET_RUNTIME_DLLS 处理导入库目标的依赖关系

CMake - How to handle dependencies of imported library targets with TARGET_RUNTIME_DLLS

在我的项目中,我依赖于一些名为 foo.

的第三方共享库

foo 本身依赖于其他一些第三方 dll(我们称之为 bar.dll),但是我的项目既没有使用它也没有暴露在 headers 中13=].

foo 目标已创建并link编辑到我的项目中,如下所示

add_library(foo SHARED IMPORTED)
set_target_properties(foo PROPERTIES
  IMPORTED_LOCATION "${foo_dll_path}"
  IMPORTED_IMPLIB   "${foo_lib_path}"
)

target_link_libraries(my_project PUBLIC foo)

稍后 post 构建事件被触发,通过 $<TARGET_RUNTIME_DLLS:my_project> 生成器表达式为所有依赖的第 3 方库创建硬 link。

如何在此设置中引入 bar.dll 以便在 $<TARGET_RUNTIME_DLLS:my_project> 中可见?

到目前为止,我尝试通过 add_library(bar UNKNOWN IMPORTED)add_library(bar SHARED IMPORTED) 添加 bar.dll 作为另一个导入目标,并相应地在 bar 上设置 IMPORTED_LOCATION,但是确实会造成 linker 错误。 示例:

add_library(bar UNKNOWN IMPORTED)
set_target_properties(bar PROPERTIES
  IMPORTED_LOCATION "${bar_dll_path}"
)
target_link_libraries(foo INTERFACE bar)

UNKNOWN 的情况下,linker 将使用 bar.dll 作为 linker 输入,这当然会失败,在 SHARED IMPORTED CMake 的情况下要求设置 IMPORTED_IMPLIB,但我既没有 bar.dll 的导入库,也不想 link my_project 反对它。

关于如何处理这个问题还有其他建议吗?

因为似乎有 no proper solution to this issue 我想出了一个涉及元目标的(可能脆弱的)解决方法:

# same as before
add_library(foo_real SHARED IMPORTED)
set_target_properties(foo_real PROPERTIES
  IMPORTED_LOCATION "${foo_dll_path}"
  IMPORTED_IMPLIB   "${foo_lib_path}"
)

# add SHARED IMPORTED target with the importlib pointing to foo_reals importlib location
add_library(bar SHARED IMPORTED)
set_target_properties(bar PROPERTIES
  IMPORTED_LOCATION "${bar_dll_path}"
  IMPORTED_IMPLIB   "${foo_lib_path}" # same lib path as for imported target foo
)

# add meta target to combine both
add_library(foo INTERFACE IMPORTED)
target_link_libraries(foo INTERFACE foo_real bar)

# finally link the meta target to the final project
target_link_libraries(my_project PUBLIC foo)

此解决方法将导致 CMake 生成一个构建脚本,将 foo.lib 多次传递给链接器,这似乎不会导致当前 MSVC 工具集出现问题。此外,bar.dll 现在将按预期成为 TARGET_RUNTIME_DLLS 的一部分。