Why Is Cmake Designed So That It Removes Runtime Path When Installing

Creating binary with CMake removes runtime path

You should look at set_target_properties command and the property BUILD_WITH_INSTALL_RPATH

http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:set_target_properties

Why does cmake's installed files differ from the actual built binary?

This is normal behavior in CMake.
When compiling you binaries the rpath to the dependencies is set in the binary, but stripped when installing it.

By default if you don't change any RPATH related settings, CMake will
link the executables and shared libraries with full RPATH to all used
libraries in the build tree. When installing, it will clear the RPATH of
these targets so they are installed with an empty RPATH.
Source

When looking up runtime dependencies the rpath is preferred over the default directories (see https://stackoverflow.com/a/33520976/4181011).
But since the rpath was removed from your library it doesn't know about you "out-of-default-directories"-dependencies.

You can manipulate the lookup with LD_LIBRARY_PATH, LD_PRELOAD or by adding the additional path to the lookup directories using ldconfig.

CMake copying Qt runtime libraries to executable output path

You explicitly ask for your result by using DESTINATION . in

    install(
DIRECTORY ${CMAKE_BINARY_DIR}/qtDeploy/
DESTINATION .
FILES_MATCHING PATTERN "*.*"
)

That could be DESTINATION ${CMAKE_INSTALL_BINDIR} to point to the same directory you use for other binaries.

Why `make install` is deleting library files *.so generated by `make`?

This happens because:

-DCMAKE_INSTALL_PREFIX=./

means that you are installing over the top of the build directory itself,
with the result that for each filename in the cmake command:

  file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/lib" TYPE SHARED_LIBRARY FILES
"path/poco/instDir/lib/libPocoEncodingsd.so.60"
"path/poco/instDir/lib/libPocoEncodingsd.so"
)

the source and destination files are the same. Cmake preemptively deletes the
destination file to replace it with the source file. Which means it has deleted
the source file. Hence your failure.

This behaviour may be a bug in cmake. On the face of it, if it checks and finds that the
destination file exists and has the same timestamp as the source file, it should consider
the destination file up to date and not attempt to replace it. But I haven't delved into that. Installing on top of your build directory is reasonably classified
under Don't do that.

Conventionally on Unix-like OSes, locally built packages shall be installed to
/usr/local. That's what /usr/local is for. Cmake, like other source package
deployment tools, respects this convention by default. So if you simply run:

cmake -DCMAKE_BUILD_TYPE=Debug ../
make
sudo make install # Or however you run `make install` as root.

then the poco libraries will be installed in /usr/local/lib and the headers
in /usr/local/include/Poco. /usr/local/lib is a default library search path for the
linker and /usr/local/include is a default header search path for the compiler.

If for some reason you don't want to install to the default prefix, then
choose some:

-DCMAKE_INSTALL_PREFIX=/not/in/the/build/dir

and you will avoid this problem.

CMake: Run-time error (dyld: Library not loaded) for dynamically linked resources on MacOS

CMake changes the RPATH for all installed targets upon running make install.

Imagine building both a shared library and an executable as part of the same CMake project. In order to be able to run the executable, it has to be able to dynamically load the shared library at runtime. Therefore, CMake by default adds the full (absolute) path to the dynamic library in the build tree to the executable's rpath. This is very convenient for developing, as we can run the executable straight from the build tree, but we probably would not want to ship the executable that way.

That's why CMake will change the rpath upon install to only contain portable paths (ie. remove the entry pointing to the build tree). That is, unless you put your shared library into one of the system default locations, the executable won't find it anymore after installing.

CMake does allow you though to specify an install rpath that will replace the removed build tree entry with your specified one. See the INSTALL_RPATH and INSTALL_RPATH_USE_LINK_PATH target properties for details.

Since all of this rpath stuff is 100% platform-dependent, OSX comes with its own, special rules. A pretty comprehensive explanation can be found on the (unfortunately rather outdated) CMake wiki:

Unlike other UNIXes, the Darwin linker, dyld, locates dependent
dynamic libraries using the full path to each dylib. For example, in
an executable "foo", the full paths recorded are the install names for
each dependent dylib. And the library "/usr/lib/libSystem.dylib" has
an install name of "/usr/lib/libSystem.B.dylib" as given by "otool
-D". When linked into "foo", "foo" has a dependency on "/usr/lib/libSystem.B.dylib". This dependency can be seen with "otool
-L foo". For relocatable binaries, @executable_path, @loader_path and @rpath are available to use. In the "foo" example, @executable_path
and @loader_path are substituted for the location of "foo". @rpath is
substituted with the RPATHs in "foo" to locate dependent dylibs. Thus
the RPATH mechanism comes into play. The linker will search for
@rpath/ dependencies in the following order:

  • DYLD_LIBRARY_PATH - an
    environment variable which holds a list of directories
  • RPATH - a list
    of directories which is linked into the executable. These can contain
    @loader_path and @executable_path.
  • builtin directories - /lib /usr/lib
  • DYLD_FALLBACK_LIBRARY_PATH - an environment variable which holds a
    list of directories

You should be able to solve this by tuning the respective target properties, but it is rather fiddly and can be quite a pain to get right.



Related Topics



Leave a reply



Submit