[Discourse.ros.org] [Release] Is it a good practice to force `RPATH` to be embedded in the installed targets?

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

[Discourse.ros.org] [Release] Is it a good practice to force `RPATH` to be embedded in the installed targets?

William Woodall via ros-users



For one of the packages I maintain ([parrot_arsdk](https://github.com/AutonomyLab/parrot_arsdk)), I modified the install rules to install all the libraries to a sub folder of ` ${CATKIN_PACKAGE_LIB_DESTINATION}` (i.e. ` ${CATKIN_PACKAGE_LIB_DESTINATION}/parrot_arsdk`). The rational behind this is to prevent some of the libraries that are custom built as part of the SDK (e.g. `curl` and `libressl`) to be picked up by other ROS packages by accident.

When compiling a dependent package (e.g. [bebop_autonomy](https://github.com/AutonomyLab/bebop_autonomy)) from source everything is fine. The compiled binary is linked against the correct `parrot_arsdk` libraries (since `RPATH` is embedded in the files created in the `build/devel` space). However when `install` rules are applied, `RPATH` information are stripped from the binaries (this is the default behaviour), so unless `LD_LIBRARY_PATH` is manually set, it is not possible to execute those binaries from the `install` space.

[My workaround](https://github.com/AutonomyLab/bebop_autonomy/commit/aef8a5d7127a59298668343942cfbebc84ec5330#diff-ba723d57ee1ae13ecda9443f17d179d3R35) for this problem was to add the following line to `CMakeLists.txt` of the dependent package (`bebop_driver`):

```cmake
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
```
This fixes the issue on my local `catkin` workspace since the binaries installed into the `install` space now have full `RPATH` information embedded in them. However I am not sure if this is the best way to fix this issue and if this approach is going to work when the binaries are built on the build farm. Any comment or suggestion is really appreciated.

PS. This is to confirm that the `RPATH` information is indeed embedded in the installed targets:


    $ ldd catkin_ws/install/lib/libbebop.so  | grep ar
    libarcontroller.so => /full/path/to/catkin_ws/install/lib/parrot_arsdk/libarcontroller.so (0x00007fcfcd24f000)






---
[Visit Topic](https://discourse.ros.org/t/is-it-a-good-practice-to-force-rpath-to-be-embedded-in-the-installed-targets/1335/1) or reply to this email to respond.


If you do not want to receive messages from ros-users please use the unsubscribe link below. If you use the one above, you will stop all of ros-users from receiving updates.
______________________________________________________________________________
ros-users mailing list
[hidden email]
http://lists.ros.org/mailman/listinfo/ros-users
Unsubscribe: <http://lists.ros.org/mailman//options/ros-users>
Reply | Threaded
Open this post in threaded view
|

[Discourse.ros.org] [Release] Is it a good practice to force `RPATH` to be embedded in the installed targets?

William Woodall via ros-users



As you suspect, this won't work when binary packages are built on the build farm. The generated binaries will include the full path to where `libarcontroller.so` was on the build farm, which will not be where it is on the machine where you install the .deb. So while building would work, the installed version will be unusable.

Usually, one would simply ensure that all required libraries are properly installed into a location on the `LD_LIBRARY_PATH`, but as you said you can't do that:

> The rational behind this is to prevent some of the libraries that are custom built as part of the SDK (e.g. curl and libressl) to be picked up by other ROS packages by accident.

I have a similar problem, where the manufacturer provides precompiled libraries that interfere with system libraries (such as Qt) and therefore must not be on the `LD_LIBRARY_PATH` for the other packages. My "solution" is to only set the `LD_LIBRARY_PATH` for the node when it's launched:

https://github.com/uos/basler_tof/blob/810c8aee1b396d1ad46e785c1aca3859adf360f9/launch/includes/device.launch.xml#L26

This is however a very dirty hack (for starters, the `env` launch file tag has been deprecated since Fuerte), and I would be interested in a proper solution as well.






---
[Visit Topic](https://discourse.ros.org/t/is-it-a-good-practice-to-force-rpath-to-be-embedded-in-the-installed-targets/1335/2) or reply to this email to respond.


If you do not want to receive messages from ros-users please use the unsubscribe link below. If you use the one above, you will stop all of ros-users from receiving updates.
______________________________________________________________________________
ros-users mailing list
[hidden email]
http://lists.ros.org/mailman/listinfo/ros-users
Unsubscribe: <http://lists.ros.org/mailman//options/ros-users>
Reply | Threaded
Open this post in threaded view
|

[Discourse.ros.org] [Release] Is it a good practice to force `RPATH` to be embedded in the installed targets?

William Woodall via ros-users
In reply to this post by William Woodall via ros-users



In general I you shouldn't set an `RPATH` on the installed binaries / libraries as a developer. However, if you're packaging for a specific distribution you know more about the target system than the original developer, and setting an `RPATH` could be a good solution. The same could be true when doing local installs in your home folder.

In short, my view boils down to this: maintainers / developers shouldn't mess with `RPATH`s, but users/packagers can have valid reasons. Of course you may be both at the same time, but you should still keep the separation in mind since other users/packagers may not want an `RPATH` in the installed targets.

[quote="Martin_Guenther, post:2, topic:1335"]
I have a similar problem, where the manufacturer provides precompiled libraries that interfere with system libraries (such as Qt) and therefore must not be on the LD_LIBRARY_PATH for the other packages. My "solution" is to only set the LD_LIBRARY_PATH for the node when it's launched:
[/quote]

Another option is to use a tool like `patchelf` to set an `RPATH` in the precompiled binaries. I tend to do this with closed source binaries that ship a bunch of conflicting libraries. You won't need to set `LD_LIBRARY_PATH` then. If you do prefer `LD_LIBRARY_PATH` but you can't use an `env` tag, you can use a wrapper script or call the `env` command.






---
[Visit Topic](https://discourse.ros.org/t/is-it-a-good-practice-to-force-rpath-to-be-embedded-in-the-installed-targets/1335/3) or reply to this email to respond.


If you do not want to receive messages from ros-users please use the unsubscribe link below. If you use the one above, you will stop all of ros-users from receiving updates.
______________________________________________________________________________
ros-users mailing list
[hidden email]
http://lists.ros.org/mailman/listinfo/ros-users
Unsubscribe: <http://lists.ros.org/mailman//options/ros-users>
Reply | Threaded
Open this post in threaded view
|

[Discourse.ros.org] [Release] Is it a good practice to force `RPATH` to be embedded in the installed targets?

William Woodall via ros-users
In reply to this post by William Woodall via ros-users



Thanks @Martin_Guenther and @de-vri-es for your insights and comments.

@Martin_Guenther

I really liked the `env`-based method. I've never fully understood how `env` tag is deprecated but is still referenced in the documentation. Does your method work on *Kinetic*? I've seen the wrapper script method mentioned by @de-vri-es in other projects. I think I will go with that solution for now. The downside is running any node via `rosrun` CLI is going to be a hassle for end users.

> In short, my view boils down to this: maintainers / developers shouldn't mess with RPATHs, but users/packagers can have valid reasons. Of course you may be both at the same time, but you should still keep the separation in mind since other users/packagers may not want an RPATH in the installed targets.

Good point!






---
[Visit Topic](https://discourse.ros.org/t/is-it-a-good-practice-to-force-rpath-to-be-embedded-in-the-installed-targets/1335/4) or reply to this email to respond.


If you do not want to receive messages from ros-users please use the unsubscribe link below. If you use the one above, you will stop all of ros-users from receiving updates.
______________________________________________________________________________
ros-users mailing list
[hidden email]
http://lists.ros.org/mailman/listinfo/ros-users
Unsubscribe: <http://lists.ros.org/mailman//options/ros-users>
Reply | Threaded
Open this post in threaded view
|

[Discourse.ros.org] [Release] Is it a good practice to force `RPATH` to be embedded in the installed targets?

William Woodall via ros-users
In reply to this post by William Woodall via ros-users



[quote="mani, post:4, topic:1335"]
I really liked the env-based method. I've never fully understood how env tag is deprecated but is still referenced in the documentation. Does your method work on Kinetic? I've seen the wrapper script method mentioned by @de-vri-es in other projects. I think I will go with that solution for now. The downside is running any node via rosrun CLI is going to be a hassle for end users.
[/quote]

For setting environment variables you should use the env-loader element of the [roslaunch XML machine tag](http://wiki.ros.org/roslaunch/XML/machine).






---
[Visit Topic](https://discourse.ros.org/t/is-it-a-good-practice-to-force-rpath-to-be-embedded-in-the-installed-targets/1335/5) or reply to this email to respond.


If you do not want to receive messages from ros-users please use the unsubscribe link below. If you use the one above, you will stop all of ros-users from receiving updates.
______________________________________________________________________________
ros-users mailing list
[hidden email]
http://lists.ros.org/mailman/listinfo/ros-users
Unsubscribe: <http://lists.ros.org/mailman//options/ros-users>
Reply | Threaded
Open this post in threaded view
|

[Discourse.ros.org] [Packaging and Release Management] Is it a good practice to force `RPATH` to be embedded in the installed targets?

William Woodall via ros-users
In reply to this post by William Woodall via ros-users



[quote="tfoote, post:5, topic:1335"]
For setting environment variables you should use the env-loader element of the roslaunch XML machine tag.
[/quote]

In this case, we only want to set the `LD_LIBRARY_PATH` of one specific node and must leave the other nodes on the same machine untouched. So I don't think the `env-loader` element is a good fit.






---
[Visit Topic](https://discourse.ros.org/t/is-it-a-good-practice-to-force-rpath-to-be-embedded-in-the-installed-targets/1335/6) or reply to this email to respond.


If you do not want to receive messages from ros-users please use the unsubscribe link below. If you use the one above, you will stop all of ros-users from receiving updates.
______________________________________________________________________________
ros-users mailing list
[hidden email]
http://lists.ros.org/mailman/listinfo/ros-users
Unsubscribe: <http://lists.ros.org/mailman//options/ros-users>
Reply | Threaded
Open this post in threaded view
|

[Discourse.ros.org] [Packaging and Release Management] Is it a good practice to force `RPATH` to be embedded in the installed targets?

William Woodall via ros-users
In reply to this post by William Woodall via ros-users



[quote="mani, post:4, topic:1335"]
I really liked the env-based method. I've never fully understood how env tag is deprecated but is still referenced in the documentation. Does your method work on Kinetic?
[/quote]

It definitely still works on Indigo, and I suspect it also works in Kinetic.

[quote]
I've seen the wrapper script method mentioned by @de-vri-es in other projects. I think I will go with that solution for now. The downside is running any node via rosrun CLI is going to be a hassle for end users.
[/quote]

Why? They can directly `rosrun` the wrapper script, so that's a point for the wrapper script.

On the other hand, the `env` element has the advantage that you can easily use launch file args to specify the location of the other libraries (like the `basler_tof_path` arg in my example above).

For a non-deprecated alternative to the `env` element, I like the suggestion by @de-vri-es to call the `env` command instead. You could even put it into the `launch-prefix` element of the roslaunch XML node tag.






---
[Visit Topic](https://discourse.ros.org/t/is-it-a-good-practice-to-force-rpath-to-be-embedded-in-the-installed-targets/1335/7) or reply to this email to respond.


If you do not want to receive messages from ros-users please use the unsubscribe link below. If you use the one above, you will stop all of ros-users from receiving updates.
______________________________________________________________________________
ros-users mailing list
[hidden email]
http://lists.ros.org/mailman/listinfo/ros-users
Unsubscribe: <http://lists.ros.org/mailman//options/ros-users>
Reply | Threaded
Open this post in threaded view
|

[Discourse.ros.org] [Packaging and Release Management] Is it a good practice to force `RPATH` to be embedded in the installed targets?

William Woodall via ros-users
In reply to this post by William Woodall via ros-users



Thanks @Martin_Guenther, @de-vri-es and @tfoote for your comments and suggestions. I came up with a solution based on an `env`-based wrapper script that works with both `rosrun` and within `launch` files. I could not get @tfoote's suggestion of using the `<machine>` tag to work on a local machine. I second @Martin_Guenther's [point](https://discourse.ros.org/t/is-it-a-good-practice-to-force-rpath-to-be-embedded-in-the-installed-targets/1335/6?u=mani) about this suggestion.

Here is the wrapper script I wrote:

https://github.com/AutonomyLab/bebop_autonomy/blob/adynathos-indigo-devel/bebop_driver/scripts/bebop_env_loader

It simply looks at `LD_LIBRARY_PATH` environmental variable. If it is set, it picks the first element, adds `parrot_arsdk` to the end of that element and adds the modified element to the head of `LD_LIBRARY_PATH`. Then it executes any specified binary and arguments with the `env` command using the modified `LD_LIBRARY_PATH`.

For example if `LD_LIBRARY_PATH` is set to `/opt/ros/kinetic/lib:...`, it executes the following command:

```bash
$ env LD_LIBRARY_PATH=/opt/ros/kinetic/lib/parrot_arsdk:/opt/ros/kinetic/lib:... /path/to/binary [args]
```

This way it can be used both by `rosrun` and within launch files in a quite portable way:

```bash
$ rosrun --prefix "rosrun bebop_driver bebop_env_loader" bebop_driver bebop_driver_node
```

or

```xml
<node pkg="bebop_driver" name="bebop_driver" type="bebop_driver_node" launch-prefix="$(find bebop_driver)/scripts/bebop_env_loader">
```

I did some testing and it seems to be working fine. Is this the solution you were suggesting?






---
[Visit Topic](https://discourse.ros.org/t/is-it-a-good-practice-to-force-rpath-to-be-embedded-in-the-installed-targets/1335/8) or reply to this email to respond.


If you do not want to receive messages from ros-users please use the unsubscribe link below. If you use the one above, you will stop all of ros-users from receiving updates.
______________________________________________________________________________
ros-users mailing list
[hidden email]
http://lists.ros.org/mailman/listinfo/ros-users
Unsubscribe: <http://lists.ros.org/mailman//options/ros-users>