Tux

...making Linux just a little more fun!

2-cent tip - rpath

Oscar Laycock [oscar_laycock at yahoo.co.uk]


Thu, 8 Oct 2009 02:17:44 -0700 (PDT)

This all started when I wanted to run the latest version of Firefox. I decided to build my own from source. But my kernel, assembler, compiler and C library were too old - in fact, nine years old. So I built new ones under the /usr/local directory. I used the Linux From Scratch book as a guide.

Now when I build new programs, I set the GCC compiler's "rpath" option to point to the libraries in /usr/local rather than in the usual /lib and /usr/lib. The rpath is a list of libraries at the start of a program that can tell Linux where to look for shared libraries when Linux runs a program. A program called the "dynamic linker" does the job. On my system it is "/lib/ld-linux.so.2". You can see a program's rpath by running a command such as "readelf -a /bin/ls". Of course, normally there isn't one. Also you can watch the dynamic linker at work using the "ldd" command. I set GCC's rpath by including it in the CFLAGS environment variable when configuring programs before building them. (You typically type "configure", "make" and "make install" to build a program.) I found a small number of programs ignore CFLAGS, so I made the gcc program a shell script, which then calls the real gcc with the right rpath option.

So I can now run old commands such as "ls" and "find" alongside new programs such as the KDE suite. The now eleven-year-old commands run fine on top of the recent kernel. I also put /usr/local/bin at the start of my path. This may be a security risk but my PC is not connected to the internet or a network.

There is a bit more too it. So here is the CFLAGS setting I used only few days ago:

export CFLAGS="-O2 -I. -I.. -I/usr/local/myglibc27/include -I/usr/local/include
-L/usr/local/myglibc27/lib -L/usr/local/lib -L/usr/local/lib/gcc/i686-pc-linux-gnu/4.2.3 -Wl,-rpath=/usr/local/myglibc27/lib:/usr/local/lib:/usr/local/lib/gcc/i686-pc-linux-gnu/4.2.3,-dynamic-linker=/usr/local/myglibc27/lib/ld-linux.so.2 -specs=/home/oscar/tmp/glibc/myspecs08scr -march=pentium2"

I also similarly set these environment variables: LDFLAGS, CXXFLAGS, CPPFLAGS, LIBCFLAGS, LIBCXXFLAGS. You can see that the include file path (-I's) and libraries path (-L's) match the rpath. The "-I. -I.." is there because some programs need to look at the header files in the build directory first - a bit of a quick fix. Notice how I now have two separate dynamic linkers on my PC. I had to edit the compiler specs file a little. Here is a section to really confuse you:

*startfile:
%{!shared: %{pg|p|profile:/usr/local/myglibc27/lib/gcrt1.o%s;pie:/usr/local/myglibc27/lib/Scrt1.o%s;:/usr/local/myglibc27/lib/crt1.o%s}}    /usr/local/myglibc27/lib/crti.o%s %{static:/usr/local/lib/gcc/i686-pc-linux-gnu/4.3.2/crtbeginT.o%s;shared|pie:/usr/local/lib/gcc/i686-pc-linux-gnu/4.3.2/crtbeginS.o%s;:/usr/local/lib/gcc/i686-pc-linux-gnu/4.3.2/crtbegin.o%s}

I think this is choosing which C runtime code to put at the start of the program.

And here is the shell script that stands in for gcc:

#!/bin/sh
set -xv
gccREAL -L../lib -L/usr/local/myglibc27/lib -L/usr/local/lib -L/usr/local/lib/gcc/i686-pc-linux-gnu/4.2.3 "$@" -I. -I.. -I/usr/local/myglibc27/include -I/usr/local/include -Wl,-rpath=/usr/local/myglibc27/lib:/usr/local/lib:/usr/local/lib/gcc/i686-pc-linux-gnu/4.2.3 -specs=/home/oscar/tmp/glibc/myspecs08scr -march=pentium2 -O2

To conclude, I am not sure if I would recommend this setup, but it has worked for me for several years.


Top    Back


Steve Brown [steve.stevebrown at gmail.com]


Thu, 8 Oct 2009 10:39:41 +0100

On Thu, Oct 8, 2009 at 10:17 AM, Oscar Laycock <oscar_laycock@yahoo.co.uk>wrote:

[ snippage ]

You get an awful lot for 2c these days ;-)

-- Steve


Top    Back