如何包含具有多个 dll/dylib 的外部(共享)库

How to include external (shared) library with several dlls/dylibs

本文关键字:外部 共享 dylib 何包含 dll      更新时间:2023-10-16

我需要将外部构建(共享)库集成为逻辑库 将目标构建到我的CMake配置中,该配置由几个组成 共享库文件 (DLL/dylibs)。 通常我会执行以下操作:

find_path(MyLib_INCLUDE_DIR mylib.h HINTS ${MyLib_PATH}/include)
find_library(MyLib_LIBRARY NAMES MyLib HINTS ${MyLib_PATH}/bin)
find_library(MyLib_LIBRARY_DEBUG NAMES MyLib_d ${MyLib_PATH}/bin)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(MyLib DEFAULT_MSG
MyLib_LIBRARY MyLib_LIBRARY_DEBUG MyLib_INCLUDE_DIR)
if(MyLib_FOUND AND NOT TARGET MyLib::MyLib)
set(MyLib_LIBRARIES ${MyLib_LIBRARY})
set(MyLib_INCLUDE_DIRS ${MyLib_INCLUDE_DIR})
add_library(MyLib::MyLib UNKNOWN IMPORTED)
set_target_properties(MyLib::MyLib PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${MyLib_INCLUDE_DIR}
IMPORTED_LOCATION ${MyLib_LIBRARY}
IMPORTED_LOCATION_DEBUG ${MyLib_LIBRARY_DEBUG})
mark_as_advanced(MyLib_INCLUDE_DIR MyLib_LIBRARY MyLib_LIBRARY_DEBUG)
endif()

我的理解是,add_library(... UNKOWN IMPORTED)会 自行找出共享/静态库(并基于选项BUILD_SHARED_LIBS可能,但这不应该是必需的)。然而 CMake 不允许向属性添加库列表IMPORTED_LOCATION.例如,如果我想导入 MyLib, MyLibFoo和MyLibBar都作为调试和发布版本,这不是 可以使用列出的方法。

我知道add_library(MyLib::MyLib INTERFACE IMPORTED)并设置了一个 属性的库列表INTERFACE_LINK_LIBRARIES,但是这个 在创建可重定位包的情况下是有问题的(因为 在CMake文档中提到)。此外,没有这样的 属性作为INTERFACE_LINK_LIBRARIES_DEBUG,因此它只会是 可以参考我的 外部导入的库。

那么,我应该如何将我的外部构建的库作为 可重定位就绪的逻辑 CMake 目标,实际上包括多个 调试或发布构建共享库文件?

免责声明:我已经在CMake邮件列表中问过这个问题,但到目前为止还没有收到任何答案。

但是,CMake 不允许将库列表添加到属性IMPORTED_LOCATION。

这是合乎逻辑的,因为单个库(甚至是IMPORTED)应该有一个文件。

只需为每个实际库创建一个库导入目标:

add_library(MyLib::MyLibFoo UNKNOWN IMPORTED)
set_target_properties(MyLib::MyLibFoo PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${MyLibFoo_INCLUDE_DIR}
IMPORTED_LOCATION ${MyLibFoo_LIBRARY}
IMPORTED_LOCATION_DEBUG ${MyLibFoo_LIBRARY_DEBUG})
add_library(MyLib::MyLibBar UNKNOWN IMPORTED)
set_target_properties(MyLib::MyLibBar PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${MyLibBar_INCLUDE_DIR}
IMPORTED_LOCATION ${MyLibBar_LIBRARY}
IMPORTED_LOCATION_DEBUG ${MyLibBar_LIBRARY_DEBUG})

并创建一个接口导入库目标,该目标链接在目标上方:

add_library(MyLib::MyLib INTERFACE IMPORTED)
set_property(TARGET MyLib::MyLib PROPERTY
INTERFACE_LINK_LIBRARIES MyLib::MyLibFoo MyLib::MyLibBar)

因此,当用户链接MyLib::MyLib时,他实际上链接了您的所有库。