Archive for November, 2009

Compile a program using another version of a system library with libtool

Sunday, November 29th, 2009

Anjuta needs now GTK+ 2.18.0 (in fact 2.17.10) while I haven’t updated my system and still have GTK+ 2.16.1. The obvious solution is to download GTK+ 2.18.0, compile and install it in /usr/local as other libraries but it’s not so easy.

GTK+ depends on other libraries GLib, Pango and ATK. At least my version of GLib was too old, so I have download, compiled and installed all these 3 libraries. This step is not really a problem if you have taken care to set the environment variable PKG_CONFIG_PATH=/usr/local/lib/pkgconfig. The configure script will look for a library first in usr/local/lib before checking standard location (/usr/lib).

The troubles come when compiling Anjuta. Anjuta depends on GTK+ and get the new GTK+ version in /usr/local/lib. But it has several others dependencies (by example GConf, Orbit, vte, unique) which depend themselves on GTK+ and they use the old version of GTK+. In the link command, I can see both versions of GTK+. I suppose that the linker keeps only the first one, in this case it is the old one and I get some undefined symbols.

One first easy but lengthy solution, is to download these dependencies (GConf, Orbit, vte…), compile and install them. The problem is that these libraries probably have a few other dependencies so I will have to download and compile quite a lots of packages.

There is a second solution. As GTK+ keeps a backward binary compatibility, there is no need to recompile vte with a newer version of GTK+. Even if it has been compiled with GTK+ 2.16.0, it should work fine with GTK+ 2.18.0. If I can tell these libraries to use the new version everything should work.

How the linker is looking for libraries ? There are several ways to tune this search. One easy way for my case is to define another environment variable LD_LIBRARY_PATH=/usr/local/lib. With this, all programs looking for a dynamic library will look in /usr/local/lib before checking standard paths. This is used at link time and at run time. So all programs will now use the new version of GTK+. But when I’m trying to compile Anjuta, I still get both versions of GTK+.

Why ? The problems comes from libtool. It is a program part of the autotools stuff, which is taking care of building libraries the goal is to make it easier to build shared libraries on all possible platforms. On Linux, the dynamic linker is quite capable so it doesn’t need more information than the library name. On other platform it needs more informations like the list of all dependencies of the library, so even on Linux libtool is replacing each library with a small text file containing these information. It is the .la file. Indeed we can open it in a text editor and see all dependencies using absolute pathes. So by example libOrbit-2 depends on /usr/lib/libglib-2.0.la.

So, to solve my problem I have done the following:

  • Copy  /usr/lib/libvte.la  /usr/lib/libORBit-2.la  /usr/lib/libgconf-2.la  /usr/lib/libunique-1.0.la to /usr/local/lib
  • Edit all these files to change the path of  GLib, GTK+, Pango and ATK to /usr/local/lib

When it is done, libtool will find these .la file before the one in /usr/lib and so add the correct dependencies. It will still use the libraries in /usr/lib as the path of the library is included inside the .la file. (libdir). You will a warning at link time:

libtool: link: warning: `/usr/local/lib/libgconf-2.la’ seems to be moved.

Then, when you compile a library, libtool will create a .la file for this library and it will be put normally in /usr/local/lib. But the absolute pathes of the dependencies in the .la file seems to depend on the path of the .pc file (used by pkg-config). So It is useful to copy the .pc file in /usr/local/lib/pkgconfig too.