!!! warning This page will soon replace https://docs.easybuild.io/en/latest/RPATH-support.html.
**
It still needs to be ported from *reStructuredText* (.rst) to *MarkDown* (.md),
and you can help with that!
**
- source: [`docs/RPATH-support.rst` in `easybuilders/easybuild` repo](https://raw.githubusercontent.com/easybuilders/easybuild/develop/docs/RPATH-support.rst)
- target: [`docs/rpath-support.md` in `easybuilders/easybuild-docs` repo](https://github.com/easybuilders/easybuild-docs/tree/main/docs/rpath-support.md)
See <https://github.com/easybuilders/easybuild-docs> for more information.
.. _rpath_support:
Support for RPATH
=================
Since EasyBuild v3.5.2, (stable) support is available for using RPATH.
.. contents::
:depth: 3
:backlinks: none
.. _rpath_support_what:
What is RPATH?
--------------
RPATH is a mechanism to include a list of directories in a binary where required shared libraries may be available.
These locations are considered by the dynamic loader (``ld*.so``) to locate the libraries that are required by a particular binary.
Hence, instructing the dynamic linker (``ld``) to include RPATH entries in a binary is an alternative to specifying library locations
through ``$LD_LIBRARY_PATH``.
For more information on RPATH, see https://linux.die.net/man/8/ld-linux
.. _rpath_support_why:
Why RPATH?
----------
Using RPATH can be interesting for a number of reasons:
* it can help to avoid a (too) large environment, since:
* ``$LD_LIBRARY_PATH`` does not need to be set anymore for all dependencies providing libraries
* it leads to fewer runtime dependencies (and hence fewer modules need to be loaded)
* binaries can be used without problems w.r.t. resolving required libraries in other environments
* it may result in better startup performance, since ``$LD_LIBRARY_PATH`` does not have to be iterated over
A minor downside is that it becomes less trivial to move installations of dependencies to a different location
(which is something that you should not do without good reason anyway).
.. _rpath_support_enable:
Enabling RPATH linking
----------------------
To instruct EasyBuild to enable RPATH linking, use the ``--rpath`` configuration option.
.. _rpath_support_implementation:
Implementation
--------------
When EasyBuild is configured to use RPATH, wrapper scripts are put in place for the dynamic linker commands (``ld``, ``ld.gold``),
as well as for every compiler command that is part of the toolchain being used. This is done during the ``prepare`` step.
The wrapper scripts will analyze and rewrite the list of arguments supplied to the command they are wrapping as needed, i.e.:
* inject an ``-rpath`` argument for every ``-L`` argument that specifies a library directory (with some exceptions, see also :ref:`rpath_support_filtered_paths`)
* filter out arguments that affect RPATH (e.g., ``--enable-new-dtags``)
* ensure that the library subdirectories (``lib``, ``/lib64``) of the installation directory also have an RPATH entry
* include additional arguments related to RPATH (e.g. ``--disable-new-dtags``)
As such, ``ps`` may show something like::
\_ /bin/bash /tmp/eb-M3393U/tmpRVJqwr/rpath_wrappers/gcc -O2 example.c -L/example -lexample
| \_ /example/software/GCCcore/4.9.3/bin/gcc -Wl,-rpath=$ORIGIN/../lib -Wl,-rpath=$ORIGIN/../lib64 -Wl,--disable-new-dtags -Wl,-rpath=/example -O2 example.c -L/example -lexample
Here, ``/tmp/eb-M3393U/tmpRVJqwr/rpath_wrappers/gcc`` is the wrapper script for ``gcc``,
which tweaks the list of command line arguments for ``gcc``
before calling out to the real ``gcc`` command (i.e., ``/example/software/GCCcore/4.9.3/bin/gcc`` in this example).
.. _rpath_support_impl_logs:
RPATH wrapper script log files
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When EasyBuild is used in debug mode (``--debug``), the RPATH wrapper script will generate log files in
the temporary directory used by EasyBuild, for debugging purposes::
$ ls -l /tmp/eb-_hoff5/rpath_wrapper*log | sed 's/vsc40023/example/g'
-rw-rw-r-- 1 example example 739692 Nov 16 15:50 /tmp/eb-_hoff5/rpath_wrapper_gcc.log
-rw-rw-r-- 1 example example 27814 Nov 16 15:50 /tmp/eb-_hoff5/rpath_wrapper_g++.log
-rw-rw-r-- 1 example example 1589626 Nov 16 15:50 /tmp/eb-_hoff5/rpath_wrapper_ld.gold.log
-rw-rw-r-- 1 example example 8870 Nov 16 15:50 /tmp/eb-_hoff5/rpath_wrapper_ld.log
These log files include details on every captured compiler/linker command, i.e. the original list of arguments,
the tweaked list of arguments that includes the injected ``-rpath`` arguments, etc., and may be helpful to debug the RPATH support.
.. _rpath_support_impl_overhead:
Overhead of RPATH wrapper scripts
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Wrapping each compiler and linker command being executed comes at a cost,
especially since the wrapper (shell) script calls out to a Python script (``rpath_args.py``) to do the heavy lifting.
Some early benchmarking has shown that this overhead is quite limited however,
with observed slowdowns of the build and installation procedure of 10-15%.
.. _rpath_support_filtered_paths:
Filtering RPATH entries via ``--rpath-filter``
----------------------------------------------
To avoid that the wrapper scripts inject RPATH entries for particular locations,
EasyBuild can be configured with an RPATH filter via ``--rpath-filter``.
The specified value should be a comma-separated list of (Python) regular expressions for paths.
Only paths that *match* either of the specified patterns will be filtered out.
For example, to filter out locations in either ``/opt/lib`` or ``/apps/lib``, use::
eb --rpath-filter='/opt/lib.*,/apps/lib.*'
By default, no RPATH entries will be injected for system locations
that start with either ``/lib`` (incl. ``/lib64``) or ``/usr``
(which is equivalent with ``--rpath-filter='/lib.*,/usr.*'``).
.. note:: If you are specifying ``--rpath--filter``, the default filter is *overwritten*,
so if you want to retain the filtering for system locations you should also
include ``/lib.*`` and ``/usr.*``.
For example, to also filter out paths starting with ``/example``::
eb --rpath-filter='/lib.*,/usr.*,/example.*'
.. _rpath_support_LD_LIBRARY_PATH:
Relation to ``$LD_LIBRARY_PATH``
--------------------------------
As mentioned above (:ref:`rpath_support_why`), using RPATH avoids the need to update ``$LD_LIBRARY_PATH`` for every dependency.
However, there is a chicken-or-egg situation: even though a particular dependency itself can be built and installed using RPATH,
it does not mean that software packages that require it *have* to built with RPATH...
Hence, EasyBuild does not automatically exclude ``$LD_LIBRARY_PATH`` update statements from the generated module files.
You need to configure EasyBuild to do so, using the ``---filter-env-vars`` configuration option.
For example::
eb --rpath --filter-env-vars=LD_LIBRARY_PATH example.eb
To consistently configure EasyBuild to both use RPATH and not include ``$LD_LIBRARY_PATH`` update statements in generated
module files, you can use either environment variables or a configuration file; see :ref:`configuring_easybuild`.