Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c++

cmake

I need to integrate an externally built (shared) library as a logical build target into my CMake configuration which consists of several shared library files (dlls/dylibs). Usually I'd do the following:

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()

My understanding is that add_library(... UNKOWN IMPORTED) will CMake figure out shared/static libraries by itself (and based on the option BUILD_SHARED_LIBS probably, but this shouldn't be necessary). However, CMake doesn't allow to add a list of libraries to the property IMPORTED_LOCATION. For Instance, in case I want to import MyLib, MyLibFoo and MyLibBar both as debug and release builds, this is not possible using the listed approach.

I'm aware of add_library(MyLib::MyLib INTERFACE IMPORTED) and set a list of libraries to the property INTERFACE_LINK_LIBRARIES, but this is problematic in the case of creating relocatable packages (as mentioned in the CMake documentation). Furthermore, there's no such property as INTERFACE_LINK_LIBRARIES_DEBUG, thus it would only be possible to refer to either the release or debug builds of my externally imported library.

So, how am I supposed to import my externally built library as an relocatable-ready logical CMake target which actually includes several either debug or release build shared library files?

Disclaimer: I've already asked this on the CMake mailing list, but haven't received any answer so far.

like image 764
NewProggie Avatar asked Jan 23 '18 08:01

NewProggie


1 Answers

However, CMake doesn't allow to add a list of libraries to the property IMPORTED_LOCATION.

This is logical, because a single library (even IMPORTED) should have a single file.

Just create a library IMPORTED target per actual library:

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})

And create a single INTERFACE IMPORTED library target, which links above targets:

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

So, when user links MyLib::MyLib, he actually links all of your libraries.

like image 109
Tsyvarev Avatar answered Sep 19 '22 07:09

Tsyvarev