如何包含具有多个 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轴子图?

如何创建具有选择的多个用户模型?

具有共享滚动手势的嵌套 UITableView

多个Facebook,Twitter共享按钮在一个页面中具有自定义图像和标题

将具有外部依赖项的共享库集成到 MATLAB |即犰狳、LAPACK、BLAS