5

Situation

  • My project uses CMake and compiles without problems on Ubuntu 16.04.

  • When starting the compiled application I get the message cannot open shared object file.

  • All the shared object libs are available in the same non-standard folder (and I need them there).

  • For some reason some can be found, but others cannot.

What I need

  1. The reason why some shared objects can be found and others cannot be found. The project is pretty big with many CMake files. I tried to find the differences between the libs that can be loaded and the ones that can't, but without success. Any help that point me to the right place is welcome.
  2. A solution within CMake to make it find all the shared objects.

ldd

The ldd output shows me that most shared objects can be found. Here are some examples:

libboost_filesystem.so.1.55.0 => /path/to/libs/boost/lib/libboost_filesystem.so.1.55.0 (0x00007f2ed1fa0000)
libboost_filesystem.so.1.55.0 => /path/to/libs/boost/lib/libboost_filesystem.so.1.55.0 (0x00007f96af1f5000)
libboost_program_options.so.1.55.0 => /path/to/libs/boost/lib/libboost_program_options.so.1.55.0 (0x00007f96aef85000)
libboost_system.so.1.55.0 => /path/to/libs/boost/lib/libboost_system.so.1.55.0 (0x00007f96aed80000)

For some reason a few others cannot be found. For example:

libboost_iostreams.so.1.55.0 => not found
libboost_chrono.so.1.55.0 => not found

There are other non-boost libs that showing the same behavior, but for simplicity I am just showing the boost examples.

Workarounds already tried

Below are the workarounds that already work successfully. But I am really interested in the two points in the What I need section.

Community
  • 1
  • 1
mz1000
  • 87
  • 1
  • 6
  • 1
    `This is what I tried already...` - Did this help or not? If problem is with *RPATH*, which can be fixed with *LD_LIBRARY_PATH*, then CMake has support for *RPATH* too, see [CMake RPATH handling](https://cmake.org/Wiki/CMake_RPATH_handling). – Tsyvarev Dec 29 '16 at 22:11
  • So.. does `libboost_chrono.so.1.55.0` exist on your system and where? – cen Dec 30 '16 at 11:28
  • @cen Yes, `libboost_chrono.so.1.55.0` and all the other boost libs are in `/path/to/libs/boost/lib/`. As mentioned in the question they also can be loaded when adding the path to LD_LIBRARY_PATH environment variable. – mz1000 Dec 30 '16 at 15:39
  • @Tsyvarev Yes with LD_LIBRARY_PATH it works. – mz1000 Dec 30 '16 at 16:15
  • @Tsyvarev I checked all the CMake RPATH variables in my project. Nothing is set in the CMake files. According to the article the defaults will add all link directories to the build RPATH. I also made it explicit by setting `SET(CMAKE_SKIP_BUILD_RPATH FALSE)`. The result is still the same, some libs are found, some not. I also tried to verify with `objdump`. There is nothing related to RPATH. However, it showed RUNPATH with all the correct paths. – mz1000 Dec 30 '16 at 18:42
  • Well, according to the comment here: http://stackoverflow.com/questions/8880802/cmake-linking-shared-library you must set RPATH on your own. Did you try that already? – cen Dec 31 '16 at 15:10
  • @cen I tried it and it did not change a thing. Apparently CMAKE_INSTALL_RPATH is supposed to have effect on the install RPATH. I am not installing the application, I am trying to run it from the build path. – mz1000 Jan 01 '17 at 15:15
  • 1
    It would be interesting to know how you tell CMake to link the libraries that cannot be found. Can you post the corresponding code? – oLen Jan 06 '17 at 11:05
  • I'm running into this issue also. It WAS working on linux, then I did some work on mac and the library that's failing is using a custom module mode script, which was config mode before. – johnb003 Jul 24 '18 at 02:25

1 Answers1

0

tldr; Check that the imported library is imported as SHARED or UNKNOWN and not STATIC, and has an IMPORTED_SONAME property.

You should check how the library is being imported that you're linking.

I've analyzed a few of the config mode exported targets for static and dynamic libraries, and they are a little different in the properties they set for the target.

For example for zlib, here's the version for static libraries:

add_library(ZLIB::zlibstatic STATIC IMPORTED)
set_target_properties(ZLIB::zlibstatic PROPERTIES
  IMPORTED_LINK_INTERFACE_LANGUAGES_NOCONFIG "C"
  IMPORTED_LOCATION_NOCONFIG "${_IMPORT_PREFIX}/lib/libz.a"
)

However, for dynamic libraries it's:

add_library(ZLIB::zlib SHARED IMPORTED)
set_target_properties(ZLIB::zlib PROPERTIES
  IMPORTED_LOCATION_NOCONFIG "${_IMPORT_PREFIX}/lib/libz.so.1.2.11"
  IMPORTED_SONAME_NOCONFIG "libz.so.1"
)

In a find_package module mode script, you might think you're importing a static library, when in fact the found library is a .so, so it may use the incorrect target properties. In config mode this is not likely because it's much more explicit when defining the target. Though, module mode (cmake/findXXX.cmake), you're often defining these properties as a result of FIND_PACKAGE_HANDLE_STANDARD_ARGS _LIBRARIES variable, and it's hard to tell what you're going to get. You can use libFoo.a in the search to be more explicit or playing with CMAKE_FIND_LIBRARY_SUFFIXES.

johnb003
  • 1,821
  • 16
  • 30