如何包含具有多个 dll/dylib 的外部(共享)库
Posted
技术标签:
【中文标题】如何包含具有多个 dll/dylib 的外部(共享)库【英文标题】:How to include external (shared) library with several dlls/dylibs 【发布时间】:2021-11-14 22:07:33 【问题描述】:我需要将一个外部构建(共享)的库集成为一个逻辑 将目标构建到我的 CMake 配置中,该配置由几个 共享库文件(dlls/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)
会 CMake
自己找出共享/静态库(并基于选项
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 邮件列表上提出过这个问题,但到目前为止还没有收到任何答复。
【问题讨论】:
【参考方案1】:但是,CMake 不允许将库列表添加到属性 IMPORTED_LOCATION。
这是合乎逻辑的,因为单个库(甚至 IMPORTED)应该有一个文件。
只需为每个实际库创建一个库 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)
并创建一个单一的 INTERFACE IMPORTED 库目标,它链接上面的目标:
add_library(MyLib::MyLib INTERFACE IMPORTED)
set_property(TARGET MyLib::MyLib PROPERTY
INTERFACE_LINK_LIBRARIES MyLib::MyLibFoo MyLib::MyLibBar)
因此,当用户链接MyLib::MyLib
时,他实际上链接了您的所有库。
【讨论】:
以上是关于如何包含具有多个 dll/dylib 的外部(共享)库的主要内容,如果未能解决你的问题,请参考以下文章
如何在不增加 http 请求的情况下包含多个外部 javascript 文件
如何使用Figure(matplotlib FigureCanvasQTAgg)绘制具有多个y轴的共享x轴子图?