Rationale
Update rpath guidelines. There's no reason to forbid rpath for internal libraries so allow that usage.
Beware of Rpath
Sometimes, code will hardcode specific library paths when linking binaries (using the -rpath or -R flag). This is commonly referred to as an rpath. Normally, the dynamic linker and loader (ld.so) resolve the executable's dependencies on shared libraries and load what is required. However, when -rpath or -R is used, the location information is then hardcoded into the binary and is examined by ld.so in the beginning of the execution. Since the Linux dynamic linker is usually smarter than a hardcoded path, we usually do not permit the use of rpath in Fedora.
There is a tool called check-rpaths which is included in the rpmdevtools package. It is a good idea to add it to the %__arch_install_post
macro in your ~/.rpmmacros
config file:
%__arch_install_post \ /usr/lib/rpm/check-rpaths \ /usr/lib/rpm/check-buildroot
When check-rpaths is run, you might see output like this:
ERROR 0001: file '/usr/bin/xapian-tcpsrv' contains a standard rpath '/usr/lib64' in [/usr/lib64]
Any rpath flagged by check-rpaths MUST be removed.
Rpath for Internal Libraries
When a program installs internal libraries they are often not installed in the system path. These internal libraries are only used for the programs that are present in the package (for example, to factor out code that's common to the executables). These libraries are not intended for use outside of the package. When this occurs, it is acceptable for the programs within the package to use an rpath to find these libraries.
Example:
# Internal libraries for myapp are present in: %{_libdir}/myapp/ %{_libdir}/myapp/libmyapp.so.0.3.4 %{_libdir}/myapp/libmyapp.so # myapp has an rpath to %{_libdir}/myapp/ readelf -d /usr/bin/myapp | grep RPATH 0x0000000f (RPATH) Library rpath: [/usr/lib/myapp]
Alternatives to Rpath
Often, rpath is used because a binary is looking for libraries in a non-standard location (standard locations are /lib, /usr/lib, /lib64, /usr/lib64). If you are storing a library in a non-standard location (e.g. /usr/lib/foo/), you should include a custom config file in /etc/ld.so.conf.d/. For example, if I was putting 32 bit libraries of libfoo in /usr/lib/foo, I would want to make a file called "foo32.conf" in /etc/ld.so.conf.d/, which contained the following:
/usr/lib/foo
Make sure that you also make a 64bit version of this file (e.g. foo64.conf) as well (unless the package is disabled for 64bit architectures, of course).
Removing Rpath
There are several different ways to fix the rpath issue:
- If the application uses configure, try passing the --disable-rpath flag to configure.
- If the application uses a local copy of libtool, add the following lines to the spec after %configure:
%configure sed -i 's|^hardcode_libdir_flag_spec=.*|hardcode_libdir_flag_spec=""|g' libtool sed -i 's|^runpath_var=LD_RUN_PATH|runpath_var=DIE_RPATH_DIE|g' libtool
- Sometimes, the code/Makefiles can be patched to remove the -rpath or -R flag from being called. This is not always easy or sane to do, however.
- As a last resort, Fedora has a package called chrpath. When this package is installed, you can run
chrpath --delete
on the files which contain rpaths. So, in our earlier example, we'd run:
chrpath --delete $RPM_BUILD_ROOT%{_bindir}/xapian-tcpsrv
Make sure that you remember to add a BuildRequires: chrpath if you end up using this method.