|
1 |
| -.. _rpath_support: |
2 |
| - |
3 |
| -Support for RPATH |
4 |
| -================= |
| 1 | +# Support for RPATH {: #rpath_support } |
5 | 2 |
|
6 | 3 | Since EasyBuild v3.5.2, (stable) support is available for using RPATH.
|
7 | 4 |
|
8 |
| -.. contents:: |
9 |
| - :depth: 3 |
10 |
| - :backlinks: none |
11 |
| - |
12 |
| - |
13 |
| -.. _rpath_support_what: |
14 |
| - |
15 |
| -What is RPATH? |
16 |
| --------------- |
17 |
| - |
18 |
| -RPATH is a mechanism to include a list of directories in a binary where required shared libraries may be available. |
19 |
| -These locations are considered by the dynamic loader (``ld*.so``) to locate the libraries that are required by a particular binary. |
| 5 | +## What is RPATH? {: #rpath_support_what } |
20 | 6 |
|
21 |
| -Hence, instructing the dynamic linker (``ld``) to include RPATH entries in a binary is an alternative to specifying library locations |
22 |
| -through ``$LD_LIBRARY_PATH``. |
| 7 | +RPATH is a mechanism to include a list of directories in a binary where |
| 8 | +required shared libraries may be available. These locations are |
| 9 | +considered by the dynamic loader (`ld*.so`) to locate the libraries that |
| 10 | +are required by a particular binary. |
23 | 11 |
|
24 |
| -For more information on RPATH, see https://linux.die.net/man/8/ld-linux |
| 12 | +Hence, instructing the dynamic linker (`ld`) to include RPATH entries in |
| 13 | +a binary is an alternative to specifying library locations through |
| 14 | +`$LD_LIBRARY_PATH`. |
25 | 15 |
|
| 16 | +For more information on RPATH, see |
| 17 | +<https://linux.die.net/man/8/ld-linux> |
26 | 18 |
|
27 |
| -.. _rpath_support_why: |
28 |
| - |
29 |
| -Why RPATH? |
30 |
| ----------- |
| 19 | +## Why RPATH? {: #rpath_support_why } |
31 | 20 |
|
32 | 21 | Using RPATH can be interesting for a number of reasons:
|
33 | 22 |
|
34 |
| -* it can help to avoid a (too) large environment, since: |
35 |
| - |
36 |
| - * ``$LD_LIBRARY_PATH`` does not need to be set anymore for all dependencies providing libraries |
37 |
| - * it leads to fewer runtime dependencies (and hence fewer modules need to be loaded) |
38 |
| - |
39 |
| -* binaries can be used without problems w.r.t. resolving required libraries in other environments |
40 |
| - |
41 |
| -* it may result in better startup performance, since ``$LD_LIBRARY_PATH`` does not have to be iterated over |
42 |
| - |
43 |
| -A minor downside is that it becomes less trivial to move installations of dependencies to a different location |
44 |
| -(which is something that you should not do without good reason anyway). |
45 |
| - |
46 |
| - |
47 |
| -.. _rpath_support_enable: |
48 |
| - |
49 |
| -Enabling RPATH linking |
50 |
| ----------------------- |
51 |
| - |
52 |
| -To instruct EasyBuild to enable RPATH linking, use the ``--rpath`` configuration option. |
53 |
| - |
54 |
| - |
55 |
| -.. _rpath_support_implementation: |
56 |
| - |
57 |
| -Implementation |
58 |
| --------------- |
59 |
| - |
60 |
| -When EasyBuild is configured to use RPATH, wrapper scripts are put in place for the dynamic linker commands (``ld``, ``ld.gold``), |
61 |
| -as well as for every compiler command that is part of the toolchain being used. This is done during the ``prepare`` step. |
62 |
| - |
63 |
| -The wrapper scripts will analyze and rewrite the list of arguments supplied to the command they are wrapping as needed, i.e.: |
64 |
| - |
65 |
| -* inject an ``-rpath`` argument for every ``-L`` argument that specifies a library directory (with some exceptions, see also :ref:`rpath_support_filtered_paths`) |
66 |
| -* filter out arguments that affect RPATH (e.g., ``--enable-new-dtags``) |
67 |
| -* ensure that the library subdirectories (``lib``, ``/lib64``) of the installation directory also have an RPATH entry |
68 |
| -* include additional arguments related to RPATH (e.g. ``--disable-new-dtags``) |
69 |
| - |
70 |
| -As such, ``ps`` may show something like:: |
71 |
| - |
72 |
| - \_ /bin/bash /tmp/eb-M3393U/tmpRVJqwr/rpath_wrappers/gcc -O2 example.c -L/example -lexample |
73 |
| - | \_ /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 |
74 |
| - |
75 |
| -Here, ``/tmp/eb-M3393U/tmpRVJqwr/rpath_wrappers/gcc`` is the wrapper script for ``gcc``, |
76 |
| -which tweaks the list of command line arguments for ``gcc`` |
77 |
| -before calling out to the real ``gcc`` command (i.e., ``/example/software/GCCcore/4.9.3/bin/gcc`` in this example). |
78 |
| - |
79 |
| -.. _rpath_support_impl_logs: |
80 |
| - |
81 |
| -RPATH wrapper script log files |
82 |
| -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
83 |
| -
|
84 |
| -When EasyBuild is used in debug mode (``--debug``), the RPATH wrapper script will generate log files in |
85 |
| -the temporary directory used by EasyBuild, for debugging purposes:: |
86 |
| -
|
87 |
| - $ ls -l /tmp/eb-_hoff5/rpath_wrapper*log | sed 's/vsc40023/example/g' |
88 |
| - -rw-rw-r-- 1 example example 739692 Nov 16 15:50 /tmp/eb-_hoff5/rpath_wrapper_gcc.log |
89 |
| - -rw-rw-r-- 1 example example 27814 Nov 16 15:50 /tmp/eb-_hoff5/rpath_wrapper_g++.log |
90 |
| - -rw-rw-r-- 1 example example 1589626 Nov 16 15:50 /tmp/eb-_hoff5/rpath_wrapper_ld.gold.log |
91 |
| - -rw-rw-r-- 1 example example 8870 Nov 16 15:50 /tmp/eb-_hoff5/rpath_wrapper_ld.log |
92 |
| -
|
93 |
| -These log files include details on every captured compiler/linker command, i.e. the original list of arguments, |
94 |
| -the tweaked list of arguments that includes the injected ``-rpath`` arguments, etc., and may be helpful to debug the RPATH support. |
95 |
| -
|
96 |
| -.. _rpath_support_impl_overhead: |
97 |
| -
|
98 |
| -Overhead of RPATH wrapper scripts |
99 |
| -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
100 |
| -
|
101 |
| -Wrapping each compiler and linker command being executed comes at a cost, |
102 |
| -especially since the wrapper (shell) script calls out to a Python script (``rpath_args.py``) to do the heavy lifting. |
103 |
| -
|
104 |
| -Some early benchmarking has shown that this overhead is quite limited however, |
105 |
| -with observed slowdowns of the build and installation procedure of 10-15%. |
106 |
| -
|
107 |
| -
|
108 |
| -.. _rpath_support_filtered_paths: |
109 |
| -
|
110 |
| -Filtering RPATH entries via ``--rpath-filter`` |
111 |
| ----------------------------------------------- |
112 |
| -
|
113 |
| -To avoid that the wrapper scripts inject RPATH entries for particular locations, |
114 |
| -EasyBuild can be configured with an RPATH filter via ``--rpath-filter``. |
115 |
| -
|
116 |
| -The specified value should be a comma-separated list of (Python) regular expressions for paths. |
117 |
| -Only paths that *match* either of the specified patterns will be filtered out. |
118 |
| -
|
119 |
| -For example, to filter out locations in either ``/opt/lib`` or ``/apps/lib``, use:: |
120 |
| -
|
121 |
| - eb --rpath-filter='/opt/lib.*,/apps/lib.*' |
122 |
| -
|
123 |
| -By default, no RPATH entries will be injected for system locations |
124 |
| -that start with either ``/lib`` (incl. ``/lib64``) or ``/usr`` |
125 |
| -(which is equivalent with ``--rpath-filter='/lib.*,/usr.*'``). |
| 23 | +- it can help to avoid a (too) large environment, since: |
| 24 | + - `$LD_LIBRARY_PATH` does not need to be set anymore for all |
| 25 | + dependencies providing libraries |
| 26 | + - it leads to fewer runtime dependencies (and hence fewer modules |
| 27 | + need to be loaded) |
| 28 | +- binaries can be used without problems w.r.t. resolving required |
| 29 | + libraries in other environments |
| 30 | +- it may result in better startup performance, since |
| 31 | + `$LD_LIBRARY_PATH` does not have to be iterated over |
126 | 32 |
|
127 |
| -.. note:: If you are specifying ``--rpath--filter``, the default filter is *overwritten*, |
128 |
| - so if you want to retain the filtering for system locations you should also |
129 |
| - include ``/lib.*`` and ``/usr.*``. |
| 33 | +A minor downside is that it becomes less trivial to move installations |
| 34 | +of dependencies to a different location (which is something that you |
| 35 | +should not do without good reason anyway). |
130 | 36 |
|
131 |
| - For example, to also filter out paths starting with ``/example``:: |
| 37 | +## Enabling RPATH linking {: #rpath_support_enable } |
132 | 38 |
|
133 |
| - eb --rpath-filter='/lib.*,/usr.*,/example.*' |
| 39 | +To instruct EasyBuild to enable RPATH linking, use the `--rpath` |
| 40 | +configuration option. |
| 41 | + |
| 42 | +## Implementation {: #rpath_support_implementation } |
134 | 43 |
|
| 44 | +When EasyBuild is configured to use RPATH, wrapper scripts are put in |
| 45 | +place for the dynamic linker commands (`ld`, `ld.gold`), as well as for |
| 46 | +every compiler command that is part of the toolchain being used. This is |
| 47 | +done during the `prepare` step. |
135 | 48 |
|
136 |
| -.. _rpath_support_LD_LIBRARY_PATH: |
| 49 | +The wrapper scripts will analyze and rewrite the list of arguments |
| 50 | +supplied to the command they are wrapping as needed, i.e.: |
137 | 51 |
|
138 |
| -Relation to ``$LD_LIBRARY_PATH`` |
139 |
| --------------------------------- |
| 52 | +- inject an `-rpath` argument for every `-L` argument that specifies a |
| 53 | + library directory (with some exceptions, see also |
| 54 | + [Filtering RPATH entries via `--rpath-filter`][rpath_support_filtered_paths]) |
| 55 | +- filter out arguments that affect RPATH (e.g., `--enable-new-dtags`) |
| 56 | +- ensure that the library subdirectories (`lib`, `/lib64`) of the |
| 57 | + installation directory also have an RPATH entry |
| 58 | +- include additional arguments related to RPATH (e.g. |
| 59 | + `--disable-new-dtags`) |
| 60 | + |
| 61 | +As such, `ps` may show something like: |
| 62 | + |
| 63 | +``` console |
| 64 | +\_ /bin/bash /tmp/eb-M3393U/tmpRVJqwr/rpath_wrappers/gcc -O2 example.c -L/example -lexample |
| 65 | +| \_ /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 |
| 66 | +``` |
| 67 | + |
| 68 | +Here, `/tmp/eb-M3393U/tmpRVJqwr/rpath_wrappers/gcc` is the wrapper |
| 69 | +script for `gcc`, which tweaks the list of command line arguments for |
| 70 | +`gcc` before calling out to the real `gcc` command (i.e., |
| 71 | +`/example/software/GCCcore/4.9.3/bin/gcc` in this example). |
| 72 | + |
| 73 | +### RPATH wrapper script log files {: #rpath_support_impl_logs } |
| 74 | + |
| 75 | +When EasyBuild is used in debug mode (`--debug`), the RPATH wrapper |
| 76 | +script will generate log files in the temporary directory used by |
| 77 | +EasyBuild, for debugging purposes: |
| 78 | + |
| 79 | +``` console |
| 80 | +$ ls -l /tmp/eb-_hoff5/rpath_wrapper*log | sed 's/vsc40023/example/g' |
| 81 | +-rw-rw-r-- 1 example example 739692 Nov 16 15:50 /tmp/eb-_hoff5/rpath_wrapper_gcc.log |
| 82 | +-rw-rw-r-- 1 example example 27814 Nov 16 15:50 /tmp/eb-_hoff5/rpath_wrapper_g++.log |
| 83 | +-rw-rw-r-- 1 example example 1589626 Nov 16 15:50 /tmp/eb-_hoff5/rpath_wrapper_ld.gold.log |
| 84 | +-rw-rw-r-- 1 example example 8870 Nov 16 15:50 /tmp/eb-_hoff5/rpath_wrapper_ld.log |
| 85 | +``` |
| 86 | + |
| 87 | +These log files include details on every captured compiler/linker |
| 88 | +command, i.e. the original list of arguments, the tweaked list of |
| 89 | +arguments that includes the injected `-rpath` arguments, etc., and may |
| 90 | +be helpful to debug the RPATH support. |
| 91 | + |
| 92 | +### Overhead of RPATH wrapper scripts {: #rpath_support_impl_overhead } |
| 93 | + |
| 94 | +Wrapping each compiler and linker command being executed comes at a |
| 95 | +cost, especially since the wrapper (shell) script calls out to a Python |
| 96 | +script (`rpath_args.py`) to do the heavy lifting. |
| 97 | + |
| 98 | +Some early benchmarking has shown that this overhead is quite limited |
| 99 | +however, with observed slowdowns of the build and installation procedure |
| 100 | +of 10-15%. |
| 101 | + |
| 102 | +## Filtering RPATH entries via `--rpath-filter` {: #rpath_support_filtered_paths } |
| 103 | + |
| 104 | +To avoid that the wrapper scripts inject RPATH entries for particular |
| 105 | +locations, EasyBuild can be configured with an RPATH filter via |
| 106 | +`--rpath-filter`. |
| 107 | + |
| 108 | +The specified value should be a comma-separated list of (Python) regular |
| 109 | +expressions for paths. Only paths that *match* either of the specified |
| 110 | +patterns will be filtered out. |
| 111 | + |
| 112 | +For example, to filter out locations in either `/opt/lib` or |
| 113 | +`/apps/lib`, use: |
| 114 | + |
| 115 | +``` shell |
| 116 | +eb --rpath-filter='/opt/lib.*,/apps/lib.*' |
| 117 | +``` |
| 118 | + |
| 119 | +By default, no RPATH entries will be injected for system locations that |
| 120 | +start with either `/lib` (incl. `/lib64`) or `/usr` (which is equivalent |
| 121 | +with `--rpath-filter='/lib.*,/usr.*'`). |
| 122 | + |
| 123 | +!!! note |
| 124 | + If you are specifying `--rpath--filter`, the default filter is *overwritten*, |
| 125 | + so if you want to retain the filtering for system locations you |
| 126 | + should also include `/lib.*` and `/usr.*`. |
| 127 | + For example, to also filter out paths starting with `/example`: |
140 | 128 |
|
141 |
| -As mentioned above (:ref:`rpath_support_why`), using RPATH avoids the need to update ``$LD_LIBRARY_PATH`` for every dependency. |
| 129 | + ``` shell |
| 130 | + eb --rpath-filter='/lib.*,/usr.*,/example.*' |
| 131 | + ``` |
142 | 132 |
|
143 |
| -However, there is a chicken-or-egg situation: even though a particular dependency itself can be built and installed using RPATH, |
144 |
| -it does not mean that software packages that require it *have* to built with RPATH... |
| 133 | +## Relation to `$LD_LIBRARY_PATH` {: #rpath_support_LD_LIBRARY_PATH } |
145 | 134 |
|
146 |
| -Hence, EasyBuild does not automatically exclude ``$LD_LIBRARY_PATH`` update statements from the generated module files. |
147 |
| -You need to configure EasyBuild to do so, using the ``---filter-env-vars`` configuration option. |
| 135 | +As mentioned above ([Why RPATH?][rpath_support_why]), |
| 136 | +using RPATH avoids the need to update `$LD_LIBRARY_PATH` for every |
| 137 | +dependency. |
148 | 138 |
|
149 |
| -For example:: |
| 139 | +However, there is a chicken-or-egg situation: even though a particular |
| 140 | +dependency itself can be built and installed using RPATH, it does not |
| 141 | +mean that software packages that require it *have* to built with |
| 142 | +RPATH... |
150 | 143 |
|
151 |
| - eb --rpath --filter-env-vars=LD_LIBRARY_PATH example.eb |
| 144 | +Hence, EasyBuild does not automatically exclude `$LD_LIBRARY_PATH` |
| 145 | +update statements from the generated module files. You need to configure |
| 146 | +EasyBuild to do so, using the `---filter-env-vars` configuration option. |
152 | 147 |
|
153 |
| -To consistently configure EasyBuild to both use RPATH and not include ``$LD_LIBRARY_PATH`` update statements in generated |
154 |
| -module files, you can use either environment variables or a configuration file; see :ref:`configuring_easybuild`. |
| 148 | +For example: |
| 149 | + |
| 150 | +``` shell |
| 151 | +eb --rpath --filter-env-vars=LD_LIBRARY_PATH example.eb |
| 152 | +``` |
| 153 | + |
| 154 | +To consistently configure EasyBuild to both use RPATH and not include |
| 155 | +`$LD_LIBRARY_PATH` update statements in generated module files, you can |
| 156 | +use either environment variables or a configuration file; see |
| 157 | +[Configuring EasyBuild][configuring_easybuild]. |
0 commit comments