2

I'm new to cmake, so I'm having trouble figuring out how to model the following: My program requires a third party library that I only have access to in the form of headers and *.so files. It also ships many of its dependencies as *.so files. How do I make sure that everything compiles and links correctly, ideally in the "correct" cmake way?

I've tried this

cmake_minimum_required (VERSION 3.8)
project ("Test")

add_executable (MyApp "MyApp.cpp")
link_directories("/path/to/lib")
target_include_directories(MyApp PUBLIC "/path/to/headers")

This compiles but fails at the linking stage.

Then I tried

cmake_minimum_required (VERSION 3.8)
project ("Test")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
add_executable (MyApp "MyApp.cpp")
find_package(Library REQUIRED)
target_link_libraries(MyApp PUBLIC Library::Library)

And cmake/FindLibrary.cmake following https://pabloariasal.github.io/2018/02/19/its-time-to-do-cmake-right/ (truncated):

...
if(Library_FOUND AND NOT TARGET Library::Library)
    add_library(Library::Library SHARED IMPORTED)
    set_target_properties(Library::Library PROPERTIES
        INTERFACE_INCLUDE_DIRECTORIES "${Library_INCLUDE_DIR}"
    )
    set_target_properties(Library::Library PROPERTIES
        IMPORTED_LOCATION "/path/to/library.so"
    )
endif()

This compiles and links, but the required other *.so files are not found at runtime. I suppose I need to add them also as libraries somehow, although I don't want them to be exported in FindLibrary.cmake. How do I do this correctly?

Scaatis
  • 137
  • 2
  • 10

1 Answers1

0

You can use IMPORTED libraries:

add_library(externalLib SHARED IMPORTED GLOBAL)
set_property(TARGET externalLib PROPERTY IMPORTED_LOCATION "/path/to/lib.so")
target_include_directories(externalLib INTERFACE "/path/to/headers")
target_link_directories(externalLib INTERFACE /path/to/libs)
target_link_libraries(externalLib INTERFACE -ldep1 -ldep2)

Then you can just depend on it:

target_link_libraries(MyApp PRIVATE externalLib)
Artefacto
  • 96,375
  • 17
  • 202
  • 225
  • This does not work, I get "error: 'externalLib-NOTFOUND', needed by 'MyApp', missing and no known rule to make it" – Scaatis Nov 13 '20 at 15:15
  • 1
    @Scaatis ah it's just missing the location of the library. I'll add it – Artefacto Nov 13 '20 at 15:25
  • That allowed me to build and link again, but when I run it, it still does not find the dependencies. I am on Visual Studio and the build is automatically in a different folder. Could it have something to do with that? I tried adding `set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)` but that didn't help either – Scaatis Nov 13 '20 at 15:31
  • when you run with VERBOSE=1 make (if you're using makefiles), what's the command line? I've just tested this and I get `-L/path/to/lib -Wl,-rpath,/path/to/lib`. So the RPATH should be set. You can confirm with readelf – Artefacto Nov 13 '20 at 15:36
  • Thanks for all your help so far! Visual Studio default is to use Ninja as the generator. From the build.ninja file it indeed shows: `-Wl,-rpath,/path/to/lib` and readelf shows `(RUNPATH) Library runpath: [/path/to/lib]` so maybe this is a bug/limitation in Visual Studio? OK, maybe not: I ran cmake and make manualle (with makefiles like you said). The parameters are there, but it is still not finding the libraries... – Scaatis Nov 13 '20 at 15:47
  • 1
    I am getting closer to an answer: Following this answer https://stackoverflow.com/questions/52018092/how-to-set-rpath-and-runpath-with-gcc-ld I added `add_link_options("-Wl,--disable-new-dtags")` and now it works as expected. I'm really not sure what to make of that as I'm quite new to C++ development... – Scaatis Nov 13 '20 at 16:17