Rpath linux ��� ���

Содержание
  1. Rpath linux ��� ���
  2. Setting RPATH and RUNPATH
  3. rpath vs runpath
  4. rpath
  5. runpath
  6. Conclusion
  7. How to set RPATH and RUNPATH with GCC/LD?
  8. Can I change ‘rpath’ in an already compiled binary?
  9. 4 Answers 4
  10. GitLab Community Project information Project information Activity Members Analytics Analytics Value stream Wiki Wiki Activity Collapse sidebar Close sidebar RPATH handling CMake gives the user complete control over the RPATH of executables and libraries created using CMake. What is RPATH? If an executable «foo» links to the shared library «bar», the library «bar» has to be found and loaded when the executable «foo» is executed. This is the job of the linker, under Linux this is usually ld.so . The linker searches a set of directories for the library bar, which will under most UNIXes have the name libbar.so . The linker will search the libraries in the following directories in the given order: RPATH — a list of directories which is linked into the executable, supported on most UNIX systems. It is ignored if RUNPATH is present. LD_LIBRARY_PATH — an environment variable which holds a list of directories RUNPATH — same as RPATH , but searched after LD_LIBRARY_PATH , supported only on most recent UNIX systems, e.g. on most current Linux systems /etc/ld.so.conf — configuration file for ld.so which lists additional library directories builtin directories — basically /lib and /usr/lib There are different reasons why search directories additional to the builtin ones can be needed — a user may install a library privately into his home directory, e.g. /lib/ , or there may be two or more versions of the same library installed, e.g. /opt/kde3/lib/libkdecore.so and /opt/kde4/lib/libkdecore.so . For the first case it would work if the user would set LD_LIBRARY_PATH accordingly: This will break for the second case, where for some programs /opt/kde3/lib has to be searched and for other applications /opt/kde4/lib has to be searched, but in no case both. The only way to have an executable-dependent library search path is by using RPATH (or RUNPATH , but this isn’t supported everywhere). Mac OS X and the RPATH 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 CMake and the RPATH With CMake the developer has full control over the RPATH of his executables and shared libraries. This is controlled over various target properties, see the documentation of set_target_properties() . These properties are initialized from a set of global CMake variables with the respective name. There is not something like the one «correct» RPATH set up, it depends on the wishes of the developer or distribution policies. Different RPATH settings may be required when running a program from the build tree and when running it from its install location. If the program links to shared libraries which have been also built in the same project, then the RPATH needs to point to the directories in the build tree when running the executable from the build tree, and it must not point to the build tree anymore once the executable has been installed. Unfortunately there is no easy and fast way to change the RPATH of an existing executable or shared library. Since version 2.6 CMake builds the executable with the RPATH for the build tree, and adds padding to the RPATH if the RPATH for the install tree is longer. This way, when installing the executable (or library), CMake can change the RPATH inside the existing executable. Since version 2.8.12, CMake provides the MACOSX_RPATH target property to enable RPATH on Mac OS X. It will be enabled for both the build tree and install tree. If INSTALL_NAME_DIR is set, RPATH will be overridden for the install tree. Before CMake 2.6 CMake had to link the executable (or library) again at install time, so that the installed executable had the modified RPATH. If you want the same RPATH settings for executables and shared libraries in your source tree, all you have to do is to set the CMake variables CMAKE_INSTALL_RPATH , CMAKE_SKIP_BUILD_RPATH , CMAKE_BUILD_WITH_INSTALL_RPATH , CMAKE_INSTALL_RPATH_USE_LINK_PATH once, e.g. in the top level CMakeLists.txt . Default RPATH settings 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. On Mac OS X, with MACOSX_RPATH on, the install names for dylibs will include @rpath/ prefix. This is equivalent to: With these settings you are able to run the programs directly from the build tree. Once installed, you have to ensure that they find the required shared libraries (e.g. by setting LD_LIBRARY_PATH , or by installing shared libraries into one of the default library directories). Always full RPATH In many cases you will want to make sure that the required libraries are always found independent from LD_LIBRARY_PATH and the install location. Then you can use these settings: With these settings you will be able to execute your programs from the build tree and they will find the shared libraries in the build tree and also the shared libraries outside your project, when installing all executables and shared libraries will be relinked, so they will find all libraries they need. CMAKE_INSTALL_RPATH_USE_LINK_PATH is an interesting and very useful option. When building a target with RPATH, CMake determines the RPATH by using the directories of all libraries to which this target links. Some of these libraries may be located in the same build tree, e.g. libbar.so , these directories are also added to the RPATH. If this option is enabled, all these directories except those which are also in the build tree will be added to the install RPATH automatically. The only directories which may then still be missing from the RPATH are the directories where the libraries from the same project (i.e. libbar.so) are installed to. If the install directory for the libraries is not one of the systems default library directories, you have to add this directory yourself to the install RPATH by setting CMAKE_INSTALL_RPATH accordingly. If your library is created and installed like this: then you have to set the CMAKE_INSTALL_RPATH as shown above. If you are using some variable as destination for the library, you have to add this to CMAKE_INSTALL_RPATH . If you want very tight control over the RPATH in the installed executable, you can disable CMAKE_INSTALL_RPATH_USE_LINK_PATH and just set the complete RPATH yourself via CMAKE_INSTALL_RPATH . No RPATH at all There is a builtin CMake option CMAKE_SKIP_RPATH , if it is enabled all other RPATH related options are ignored, no RPATH is built into anything. Different RPATH settings within one project Using the CMake variables as shown above you can get a global setup for RPATH for the whole project. If you need different RPATH settings for some targets, you have to use set_target_properties() to set the respective properties, which have the same names as the variables, but without the CMAKE_ prefix. Common questions Q) I have created an executable like this: When I run the one that is created with make , it works fine. However, when I run the one that is copied by make install I get something like: error while loading shared libraries: libwx_gtk2u_core-2.9.so.1: cannot open shared object file: No such file or directory A) Add to your CMakeLists.txt : Recommendations $ORIGIN : On Linux/Solaris, it’s probably a very good idea to specify any RPATH setting one requires to look up the location of a package’s private libraries via a relative expression, to not lose the capability to provide a fully relocatable package. This is what $ORIGIN is for. In CMAKE_INSTALL_RPATH lines, it should have its dollar sign escaped with a backslash to have it end up with proper syntax in the final executable. See also the CMake and $ORIGIN discussion. For Mac OS X, there is a similar @rpath , @loader_path and @executable_path mechanism. While dependent libraries use @rpath in their install name, relocatable executables should use @loader_path and @executable_path in their RPATH. For example, you can set CMAKE_INSTALL_RPATH to @loader_path , and if an executable depends on @rpath/libbar.dylib , the loader will then search for @loader_path/libbar.dylib , where @rpath was effectively substituted with @loader_path . Caveats Since install-side RPATH tweaking is an operation that is done by target-specific installation handling, any target that should have its install RPATH changed (e.g. to CMAKE_INSTALL_RPATH ) needs to end up in the installation via an install(TARGETS . ) signature and not via directory-based «copying» (otherwise the project’s cmake_install.cmake file will end up without any RPATH lines). CMake Bugs At least on CMake 2.6.4 RHEL5, man cmakecommands for INSTALL_RPATH_USE_LINK_PATH pretends that this setting will append the link path to any CMAKE_INSTALL_RPATH content one specified. However, on this version, enabling INSTALL_RPATH_USE_LINK_PATH will replace it. Well, not so sure about this any more: just verified this on CMake 2.8.0, and now on both versions it does list correct changes in cmake_install.cmake . This bug may have occurred due to previously not doing per-target install() , or perhaps due to some other changes in CMake RPATH-related variables. Debugging On Linux, one may use to verify actual settings in the binary. For verifying install-/package-time RPATH behaviour, there’s often no need to go through a tiresome full (package/install package/objdump binary) cycle each time — simply analyse RPATH_CHANGE lines listed in $/cmake_install.cmake . On Mac OS X, one may use: otool -D to view the install name of a dylib otool -L to view the dependencies otool -l | grep LC_RPATH -A2 to view the RPATHs install_name_tool -id . to change an install name install_name_tool -change . to change the dependencies install_name_tool -rpath . -add_rpath . -delete_rpath . to change RPATHs This page was initially populated by conversion from its original location in another wiki. Источник
  11. RPATH handling
  12. What is RPATH?
  13. Mac OS X and the RPATH
  14. CMake and the RPATH
  15. Default RPATH settings
  16. Always full RPATH
  17. No RPATH at all
  18. Different RPATH settings within one project
  19. Common questions
  20. Recommendations
  21. Caveats
  22. CMake Bugs
  23. Debugging
Читайте также:  Ireb r7 для windows

Rpath linux ��� ���

Recently I’ve been working on the Comedi ebuild in my Gentoo overlay, wrestling with the following error:

While tracking this down the source of this error, I learned a lot about dynamic linking on Linux, so here’s the condensed version.

RPATH , RUNPATH , and LD_LIBRARY_PATH . The current state of affairs is well summarized on the Debian wiki, which lists the library search path:

  1. the RPATH binary header (set at build-time) of the library causing the lookup (if any)
  2. the RPATH binary header (set at build-time) of the executable
  3. the LD_LIBRARY_PATH environment variable (set at run-time)
  4. the RUNPATH binary header (set at build-time) of the executable
  5. /etc/ld.so.cache
  6. base library directories ( /lib and /usr/lib )

There was a big dust-up between Debian and libtool back in 1999 when libtool-generated RPATH s caused problems during the libc5 to libc6 transition. The mailing list discussion makes for amusing and informative reading, if you’ve got a spare hour or two ;). If not, you should at least read the opening post, the description of competing contracts, and Buddha Buck’s description of how linking works, although I imagine things might have changed since then. The Debian / libtool compromise (don’t set RPATH by default for directories in the dynamic linker search path) was implemented in libtool 1.5.2 (released in 2004, see the Debian wiki), so this is not as big an issue as it once was.

By the way, it looks like RUNPATH was added since 1999 as a version of RPATH that did not override LD_LIBRARY_PATH , which is good, since LD_LIBARY_PATH gives you a way to link against libraries in, say, /var/tmp/portage/sci-libs/comedilib-9999/work/comedilib-9999/lib/.libs to test your executable before installation.

Anyhow, issues with rpaths persist. Since it both hard to predict all installation configurations at compile time, and tools to change rpaths later on (i.e. chrpath and patchelf) aren’t able to increase the size of the rpath string on Linux (they can on Solaris, because Solaris leaves a bit of padding at the end of the dynamic string table in the compiled ELF file). This means you will have trouble moving a library out of the standard library path into some out-of-the-way location. However, in the more common case of installing a library into the standard library path, chrpath is the tool you need, and it solved my comedilib QA issue.

Along the way, I ran across two other interesting posts by Diego PettenГІ about not bundling libraries.

Setting RPATH and RUNPATH

Most of the time, you’ll want to avoid setting RPATH and RUNPATH and just use libraries in your usual linking path. However, sometimes they are useful. For example, SimulAVR depends on the AVR-specific libbfd , which is hopefully not in your usual path. On Gentoo, crossdev installs under /usr/lib/binutils/ :

When you link against this library, you’ll want to set RUNPATH so you don’t have to remember to use LD_LIBRARY_PATH every time you run simulavr . Of course, if you switch to a different binutils version (e.g. not git ), you’ll need to fix the RUNPATH to point to the new target (or just rebuild simulavr against the new version).

Since you’re probably not calling the linker directly when you build simulavr , you’ll want to set some linker flags at configure time:

The relevant linker flags are -rpath and —enable-new-dtags . Without —enable-new-dtags , you’ll just set the RPATH flag, which is probably not what you want. With —enable-new-dtags , you’ll set both RPAH and RUNPATH to the same value. From ld(1) :

The DT_RPATH entries are ignored if DT_RUNPATH entries exist.

so setting both is the same as just setting RUNPATH (except for tools like chrpath which are only designed to handle a single tag). You can use readelf to see if the tags were set:

On Gentoo, —enable-new-dtags has been the default since 2005, but explicitly including the flag can’t hurt ;).

Источник

rpath vs runpath

Before we understand the difference between rpath and runpath, we need to understand where they are used. Both rpath and runpath are used to specify directories to search for shared libraries(dynamic libraries). If you are not sure what shared libraries is, I have a story written on Static vs Dynamic libraries.

Shared libraries are libraries which are not bundles along with the executable. They are loaded at the run time. How does the executable know where the libraries are present? Every executable follows a sequence of directories search to search for libraries.

Let’s understand this with a small experiment. We will build a shared library and try linking it with the executable.

We can now use the library in sample executable.

The executable cannot find the library. Let’s debug to to see the paths the library is searched for.

Now let’s try to use one of the methodology LD_LIBRARY_PATH to specify the path of the library. LD_LIBRARY_PATH specifies the search path for the executable. Let’s see the the debug output

Now you can see that “.” is added to the search path and we were able to find the library and the program executed successfully. Let’s delete the library and try the same.

As we can see after it uses the LD_LIBRARY_PATH for search it uses the system path as it cannot find the library in the LD_LIBRARY_PATH paths.

Hope by now you should have a understanding of runtime paths. We used LD_LIBRARY_PATH to specify runtime path. Similarly rpath and runpath are used the specify the runtime paths to find libraries. The difference is the order in which they are searched. We will understand the order by experiments that follow.

rpath

We are using the same test programs as before.

Looking at the compile step above we include the rpath options to provide the current path. We use the “readelf” to check the path set. The output prints as expected.

Now let’s create a another similar library which displays another message, buts let’s create it another folder named overrided_library inside the current folder.

Now we will be conducting the rest of the experiments in the parent folder.

Lets execute the already created the use_shared executable but also providing the LD_LIBRARY_PATH to the library in the overrided_library path

Читайте также:  Windows search не индексирует

Let’s see the debug output of the executable load steps

The library we search for was available in the folder provided in the rpath. So it does not bother to search in the path specified from the LD_LIBRARY_PATH.

Let’s continue the example by deleting the shared library in the current path(not the one in overrided_library folder)

There we go, we have the message printed from the library in the overrided_library. Let’s see the debug message for the same

Here we see that first rpath is searched and since the library was not available so next it searched in the LD_LIBRARY_PATH.

So rpath is first searched and next LD_LIBRARY_PATH.

runpath

For this experiment we are going to use the same programs and folder structure we had for the previous experiment.

Let’s compile the executable with runpath set rather than rpath. For this we need to use “enable-new-dtags” flag.

Here we see that the message from the library in the overrided_library folder is printed. The reason is runpath comes lower in precedence to the LD_LIBRARY_PATH. Let’s see this with the debug info

We can see that the LD_LIBRARY_PATH is searched and the library is found and the runpath is not searched. Now let’s delete the library in the overrided_library folder.

We can see from the above output that the library from the runpath was executed. The reason is it did not find the library in the LD_LIBRARY_PATH. Let’s prove this using the debug info.

From this we can udestand that runpath has lower precedence than LD_LIBRARY_PATH. The order of precedence for search paths are

But why do we need two flags here rpath and runpath. Cant we live with one.

Conclusion

Earlier rpath was the only flag that existed. The problem arised that once rpath is set(which is done at the build time) we cannot override it during execution since LD_LIBRARY_PATH has lower precedence. We need to rebuild the executable everytime we need to test it with a different library which was quite annoying. That is when runpath was introduced where we could override the libraries with LD_LIBRARY_PATH which makes it easy to test accross different libraries without rebuilding it everytime.

Источник

How to set RPATH and RUNPATH with GCC/LD?

I recently encountered this problem after an upgrade of the system: using the GCC -Wl,-rpath= option works differently than before.

I used it to set the search paths to some shared libraries that were built in a sub-module of my project. At the time I considered it better than setting LD_LIBRARY_PATH system-wide (I didn’t want to set it every time I turned on the computer). Everything worked fine, and these two approaches seemed equivalent.

Now it seams that the behavior of -rpath has changed. It still works for directly dependent libraries, but not for those that link other libraries from the same directory set via -rpath= . Exporting LD_LIBRARY_PATH still works as before.

I inspected the output of the compilation using readelf and there is a difference. Before upgrade (Linux Mint 18.2 with GCC 5.4) the Dynamic section had this line:

After the upgrade (Linux Mint 19 with GCC 7.3) the line changed to:

In use RPATH but not RUNPATH? it is suggested that RPATH was replaced by RUNPATH (or that it at least servers a different purpose as it has a lower priority), but it doesn’t give an answer as to why this effects indirect linking. The libraries themselves have neither RPATH, or RUNPATH in readelf output.

So my question is this: Why has the linker suddenly started to interpret the -rpath= option differently, and is there a way to force the old behavior? (Or do something different that will yield an equivalent result.)

Another question would be: Is it possible to tell the old version of linker to produce the new output (i.e. RUNPATH instead of RPATH)?

EDIT

This is not a duplicate of How to set RunPath of a binary? — my question is the opposite: I want the behavior of RPATH. I figured it out (thanks to the tip in the comment), and I will answer my questions here.

Источник

Can I change ‘rpath’ in an already compiled binary?

I have an old executable that’s scheduled for the scrap heap, but it’s not there yet. It relies on some libs that have been removed from my environment, but I have some stub libs someplace where it works fine. Id like to point this executable to these stub libs. Yes, i could set LD_LIBRARY_PATH, but this executable is called from many scripts, and many users and I’d love to fix it in one spot.

I don’t have source for this, and would be hard to get it. I was thinking — can I edit this file, using an ELF aware editor, and add a simple PATH to rpath to have it hit the new libs? Is this possible, or once you create an ELF binary, you fix things to locations and they can’t be moved?

4 Answers 4

There is a more universal tool than chrpath called patchelf . It was originally created for use in making packages for Nix and NixOS (packaging system and a GNU/Linux distribution).

In case there is no rpath in a binary (here called rdsamp), chrpath fails:

On the other hand,

succeeds just fine.

There is a tool called chrpath which can do this — it’s probably available in your distribution’s packages.

Just like @user7610 said, the right way to go is the patchelf tool.

But, I feel that I can give a more comprehensive answer, covering all the commands one needs to do exactly that.

For a comprehensive article on the subject, click here

First of all, many developers talk about RPATH , but they actually mean RUNPATH . These are two different optional dynamic sections, and the loader handles them very differently. You can read more about the difference between them in the link I mentioned before.

For now, just remember:

  • If RUNPATH is set, RPATH is ignored
  • RPATH is deprecated and should be avoided
  • RUNPATH is preferred because it can be overridden by LD_LIBRARY_PATH

See the current R[UN]PATH

Clear the R[UN]PATH

  • Removes both RPATH and RUNPATH

Источник

GitLab
  • Community
  • Project information
    • Project information
    • Activity
    • Members
  • Analytics
    • Analytics
    • Value stream
  • Wiki
    • Wiki
  • Activity

Collapse sidebar Close sidebar

RPATH handling

CMake gives the user complete control over the RPATH of executables and libraries created using CMake.

What is RPATH?

If an executable «foo» links to the shared library «bar», the library «bar» has to be found and loaded when the executable «foo» is executed. This is the job of the linker, under Linux this is usually ld.so . The linker searches a set of directories for the library bar, which will under most UNIXes have the name libbar.so . The linker will search the libraries in the following directories in the given order:

  • RPATH — a list of directories which is linked into the executable, supported on most UNIX systems. It is ignored if RUNPATH is present.
  • LD_LIBRARY_PATH — an environment variable which holds a list of directories
  • RUNPATH — same as RPATH , but searched after LD_LIBRARY_PATH , supported only on most recent UNIX systems, e.g. on most current Linux systems
  • /etc/ld.so.conf — configuration file for ld.so which lists additional library directories
  • builtin directories — basically /lib and /usr/lib

There are different reasons why search directories additional to the builtin ones can be needed — a user may install a library privately into his home directory, e.g.

/lib/ , or there may be two or more versions of the same library installed, e.g. /opt/kde3/lib/libkdecore.so and /opt/kde4/lib/libkdecore.so .

For the first case it would work if the user would set LD_LIBRARY_PATH accordingly:

This will break for the second case, where for some programs /opt/kde3/lib has to be searched and for other applications /opt/kde4/lib has to be searched, but in no case both. The only way to have an executable-dependent library search path is by using RPATH (or RUNPATH , but this isn’t supported everywhere).

Mac OS X and the RPATH

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

CMake and the RPATH

With CMake the developer has full control over the RPATH of his executables and shared libraries. This is controlled over various target properties, see the documentation of set_target_properties() . These properties are initialized from a set of global CMake variables with the respective name. There is not something like the one «correct» RPATH set up, it depends on the wishes of the developer or distribution policies.

Different RPATH settings may be required when running a program from the build tree and when running it from its install location. If the program links to shared libraries which have been also built in the same project, then the RPATH needs to point to the directories in the build tree when running the executable from the build tree, and it must not point to the build tree anymore once the executable has been installed. Unfortunately there is no easy and fast way to change the RPATH of an existing executable or shared library. Since version 2.6 CMake builds the executable with the RPATH for the build tree, and adds padding to the RPATH if the RPATH for the install tree is longer. This way, when installing the executable (or library), CMake can change the RPATH inside the existing executable. Since version 2.8.12, CMake provides the MACOSX_RPATH target property to enable RPATH on Mac OS X. It will be enabled for both the build tree and install tree. If INSTALL_NAME_DIR is set, RPATH will be overridden for the install tree.

Before CMake 2.6 CMake had to link the executable (or library) again at install time, so that the installed executable had the modified RPATH.

If you want the same RPATH settings for executables and shared libraries in your source tree, all you have to do is to set the CMake variables CMAKE_INSTALL_RPATH , CMAKE_SKIP_BUILD_RPATH , CMAKE_BUILD_WITH_INSTALL_RPATH , CMAKE_INSTALL_RPATH_USE_LINK_PATH once, e.g. in the top level CMakeLists.txt .

Default RPATH settings

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. On Mac OS X, with MACOSX_RPATH on, the install names for dylibs will include @rpath/ prefix. This is equivalent to:

With these settings you are able to run the programs directly from the build tree. Once installed, you have to ensure that they find the required shared libraries (e.g. by setting LD_LIBRARY_PATH , or by installing shared libraries into one of the default library directories).

Always full RPATH

In many cases you will want to make sure that the required libraries are always found independent from LD_LIBRARY_PATH and the install location. Then you can use these settings:

With these settings you will be able to execute your programs from the build tree and they will find the shared libraries in the build tree and also the shared libraries outside your project, when installing all executables and shared libraries will be relinked, so they will find all libraries they need.

CMAKE_INSTALL_RPATH_USE_LINK_PATH is an interesting and very useful option. When building a target with RPATH, CMake determines the RPATH by using the directories of all libraries to which this target links. Some of these libraries may be located in the same build tree, e.g. libbar.so , these directories are also added to the RPATH. If this option is enabled, all these directories except those which are also in the build tree will be added to the install RPATH automatically. The only directories which may then still be missing from the RPATH are the directories where the libraries from the same project (i.e. libbar.so) are installed to. If the install directory for the libraries is not one of the systems default library directories, you have to add this directory yourself to the install RPATH by setting CMAKE_INSTALL_RPATH accordingly.

If your library is created and installed like this:

then you have to set the CMAKE_INSTALL_RPATH as shown above. If you are using some variable as destination for the library, you have to add this to CMAKE_INSTALL_RPATH .

If you want very tight control over the RPATH in the installed executable, you can disable CMAKE_INSTALL_RPATH_USE_LINK_PATH and just set the complete RPATH yourself via CMAKE_INSTALL_RPATH .

No RPATH at all

There is a builtin CMake option CMAKE_SKIP_RPATH , if it is enabled all other RPATH related options are ignored, no RPATH is built into anything.

Different RPATH settings within one project

Using the CMake variables as shown above you can get a global setup for RPATH for the whole project. If you need different RPATH settings for some targets, you have to use set_target_properties() to set the respective properties, which have the same names as the variables, but without the CMAKE_ prefix.

Common questions

Q) I have created an executable like this:

When I run the one that is created with make , it works fine. However, when I run the one that is copied by make install I get something like:

error while loading shared libraries: libwx_gtk2u_core-2.9.so.1: cannot open shared object file: No such file or directory

A) Add to your CMakeLists.txt :

Recommendations

$ORIGIN : On Linux/Solaris, it’s probably a very good idea to specify any RPATH setting one requires to look up the location of a package’s private libraries via a relative expression, to not lose the capability to provide a fully relocatable package. This is what $ORIGIN is for. In CMAKE_INSTALL_RPATH lines, it should have its dollar sign escaped with a backslash to have it end up with proper syntax in the final executable. See also the CMake and $ORIGIN discussion. For Mac OS X, there is a similar @rpath , @loader_path and @executable_path mechanism. While dependent libraries use @rpath in their install name, relocatable executables should use @loader_path and @executable_path in their RPATH. For example, you can set CMAKE_INSTALL_RPATH to @loader_path , and if an executable depends on @rpath/libbar.dylib , the loader will then search for @loader_path/libbar.dylib , where @rpath was effectively substituted with @loader_path .

Caveats

Since install-side RPATH tweaking is an operation that is done by target-specific installation handling, any target that should have its install RPATH changed (e.g. to CMAKE_INSTALL_RPATH ) needs to end up in the installation via an install(TARGETS . ) signature and not via directory-based «copying» (otherwise the project’s cmake_install.cmake file will end up without any RPATH lines).

CMake Bugs

At least on CMake 2.6.4 RHEL5, man cmakecommands for INSTALL_RPATH_USE_LINK_PATH pretends that this setting will append the link path to any CMAKE_INSTALL_RPATH content one specified. However, on this version, enabling INSTALL_RPATH_USE_LINK_PATH will replace it.

Well, not so sure about this any more: just verified this on CMake 2.8.0, and now on both versions it does list correct changes in cmake_install.cmake . This bug may have occurred due to previously not doing per-target install() , or perhaps due to some other changes in CMake RPATH-related variables.

Debugging

On Linux, one may use

to verify actual settings in the binary.

For verifying install-/package-time RPATH behaviour, there’s often no need to go through a tiresome full (package/install package/objdump binary) cycle each time — simply analyse RPATH_CHANGE lines listed in $/cmake_install.cmake .

On Mac OS X, one may use:

  • otool -D to view the install name of a dylib
  • otool -L to view the dependencies
  • otool -l | grep LC_RPATH -A2 to view the RPATHs
  • install_name_tool -id . to change an install name
  • install_name_tool -change . to change the dependencies
  • install_name_tool -rpath . -add_rpath . -delete_rpath . to change RPATHs

This page was initially populated by conversion from its original location in another wiki.

Источник

Оцените статью