Creating Binary with Cmake Removes Runtime Path

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 the relative path is different when I use Cmake build and VS 2019 build?

When using relative paths to load files, the resolution of the final filename depends on the current working directory. The relative path is appended to that working directory. That current working directory is not necessarily the same as the path of your application; it will be the path of the surrounding environment from which the application is started (or can be set specifically for a debug environment in most IDE's).

You don't specify exactly how you run your program when you run it not from the IDE - just by double-clicking the executable maybe? You also don't tell us where the executable is built in relation to your sources?

Specifically for running from Visual Studio, you can set the working directory in the "Debugging" section of the Project Properties.

For a more flexible solution, what I typically do is to determine the path of your executable, and then appending the relative path to load resources to that.
Basically, the full executable path is stored in argv[0] (if you have a int main(int argc, char** argv) {...}, i.e., the first element of the second argument to your main function). For more information on this, see for example the answers to this other question.

cpack (creating RPM) ignores CMAKE_INSTALL_RPATH (sets RPATH to empty string - rather than an explicit value)

I fixed this by explicitly setting the INSTALL_RPATH property value for the executable target. So, the addition of the set_target_properties line after the call to install

install( TARGETS 
cmakeFindPackageTest
RUNTIME DESTINATION ${INSTALL_DIR_BIN} )
set_target_properties( cmakeFindPackageTest PROPERTIES INSTALL_RPATH "/opt/cmakeFindPackageTest/lib" )

From the cmake/cpack documentation it seemed like setting the CMAKE_INSTALL_RPATH variable should have worked. The CMAKE_INSTALL_RPATH docs read

The rpath to use for installed targets.

A semicolon-separated list specifying the rpath to use in installed
targets (for platforms that support it). This is used to initialize
the target property INSTALL_RPATH for all targets.

CMake: Convert relative path to absolute path, with build directory as current directory

From the docs of get_filename_component (highlighting be me)
:

get_filename_component(<VAR> <FileName>
<COMP> [BASE_DIR <BASE_DIR>]
[CACHE])

Set <VAR> to the absolute path of <FileName>, where <COMP> is one of:

ABSOLUTE = Full path to file
REALPATH = Full path to existing file with symlinks resolved

If the provided <FileName> is a relative path, it is evaluated relative to the given base directory <BASE_DIR>. If no base directory is provided, the default base directory will be CMAKE_CURRENT_SOURCE_DIR.

Paths are returned with forward slashes and have no trailing slashes. If the optional CACHE argument is specified, the result variable is added to the cache.

Thus, you use:

get_filename_component(buildDirRelFilePath "${myFile}"
REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")

To convert an absolute path to a file into a relative paths, you might use the file command:

file(RELATIVE_PATH <variable> <directory> <file>)

Compute the relative path from a <directory> to a <file> and store it in the <variable>.

file(RELATIVE_PATH buildDirRelFilePath "${CMAKE_BINARY_DIR}" "${myFile}")

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