如何将外部(共享)库包含在几个dll/dylib中

New*_*gie 3 c++ cmake

我需要将外部构建的(共享)库作为逻辑构建目标集成到我的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()
Run Code Online (Sandbox Code Playgroud)

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

我知道add_library(MyLib::MyLib INTERFACE IMPORTED)并为属性设置了一个库列表INTERFACE_LINK_LIBRARIES,但是在创建可重定位包的情况下这是有问题的(如CMake文档中所述).此外,没有这样的属性INTERFACE_LINK_LIBRARIES_DEBUG,因此只能引用我外部导入的库的发布版本或调试版本.

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

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

Tsy*_*rev 6

但是,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})
Run Code Online (Sandbox Code Playgroud)

并创建一个INTERFACE IMPORTED库目标,链接上述目标:

add_library(MyLib::MyLib INTERFACE IMPORTED)
set_property(TARGET MyLib::MyLib PROPERTY
  INTERFACE_LINK_LIBRARIES MyLib::MyLibFoo MyLib::MyLibBar)
Run Code Online (Sandbox Code Playgroud)

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