> Mmm you seem really knowledgeable on this issue, do you care to give us
> a small explanation of what the rpath is for (in the ocaml case) or
> something such, which i could then later include in the
> ocaml_packaging_policy ?
Hhhmm. I do not _feel_ really knowledgeable on this issue at all.
Anyway, I will try to summarize it what is our experience. I will
also try to guess some explanations...
First of all, let's see a minimal (but already quite involved) example:
[ you find the code in attachment: it is made of several files and
directories ]
*** 1 ***
Let's start from the libA directory. Inside you will file a binding
to a C function that implements the identity function. The function
(in the file stub_a.c) is named fooA(). It is given the type
string -> string in the file a.ml. Since the binding does not depend
on any other binding (nor any other dinamically linked library), the
Makefile is quite simple: I can just use the following command to
build up the .cma, .cmxa and .so:
ocamlmklib stub_a.o a.cmo a.cmx
To make the things a bit more complex, I have added an install target
to the makefile that installs everything in ../installed (that is by
no means a standard library for the Linux loader).
[ Do make && make install ]
*** 2 ***
Let's move into the testA directory. This is a small test that uses
the library. To compile the test, I use -I ../installed. Since I am
not depending in any way at compile time on the .so that I have created
in libA, the .so is not used by the compiler/linker. Thus I have just
to say -I ../installed to tell ocaml where the .cmi/.cma files are.
If I try to execute the output, though, the loader needs to open the .so
===> I get
Fatal error: cannot load shared library dlla
Reason: dlla.so: cannot open shared object file: No such file or directory
To fix the problem, set LD_LIBRARY_PATH to ../installed
[ Note that if I installed the .so in stublibs, then I would have had no
problem at all, since the ocaml compilers hard-codes that directory
as a loader directive. ]
So far, so good.
*** 3 ***
Let's move into the libB directory. Here I am doing something nasty: if
you open stub_b.c you will see that I am using the fooA function that was
defined in stub_a.c ==> the code that was produced is now in the .so
file that I have installed in the non-standard ../installed path.
Now unset the LD_LIBRARY_PATH variable and try to do make. This time
the linker needs to know where dlla.so is! That is why I have added
a -L../installed -la directive to ocamlmklib. But... wait a moment!
There is no liba.so file in ../installed! ==> I need to create in installed
a symbolic link from dlla.so to liba.so. (Why did Xavier choose the
dllname.so scheme? I do not know!) [ Go into ../installed and create
the link ]
Now that the symbolic link is in place, we can do make and get the
library. If you look at the Makefile, I have used the following command:
ocamlmklib -o b -L../installed -la stub_b.o b.cmo b.cmx
Please, type it adding the -verbose flag: you will see that no -rpath
flag is added. (Because the ../installed path is relative).
[ We will come back to this point later. Now let's type make install and
then let's move to the test! ]
*** 4 ***
Let's go into testB and type Make. We get
ocamlc -I ../libB/ -dllib dllb -o testB testB.ml
Error on dynamically loaded library: liba.so: cannot open shared object
file: No such file or directory
make: *** [all] Error 2
What is happening here? For some reason (which one???), the linker
needs to open all the libraries required from dllb.so
(from ../libB), i.e. it needs to open liba.so. Unfortunately, it does
not use the "-L../installed" flag I have used to compile the libB
directory. Thus we are lost again. The only solution we have is to
set LD_LIBRARY_PATH again to ../installed. Now we can do make and
compile the file.
Once, we get the executable, we can run it, unless we unset
LD_LIBRARY_PATH! In we unset it, we are lost again and the loader can not
find the library (unless it is stublibs which is hard-coded...)
*** 5 ***
So far, so good. But where are the -rpath? Let's go back to the
libB directory and let's issue again the ocamlmklib command with the
-verbose flag. This time, though, use the absolute path instead of
../installed. This is what we get:
claudio@oberon:/tmp/rpath/libB$ ocamlmklib -o b -L/tmp/rpath/installed -la
stub_b.o b.cmo b.cmx -verbose
+ gcc -shared -o dllb.so stub_b.o -L/tmp/rpath/installed
-Wl,-rpath,/tmp/rpath/installed -la
^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ ar rc libb.a stub_b.o
+ ranlib libb.a
+ /usr/bin/ocamlc -a -o b.cma b.cmo -dllib -lb -cclib -lb -ccopt
-L/tmp/rpath/installed -ccopt -Wl,-rpath,/tmp/rpath/installed -cclib -la
+ /usr/bin/ocamlopt -a -o b.cmxa b.cmx -cclib -lb -ccopt
-L/tmp/rpath/installed -ccopt -Wl,-rpath,/tmp/rpath/installed -cclib -la
Xavier decided to add a -rpath option (it does so every time the -L is
followed by an absolute path). What is the gain? Type "make install"
and let's go back to testB. Unset LD_LIBRARY_PATH and try make again.
THIS TIME IT WORKS! The -rpath tells the linker where the library is
to be found! Thus we do not need to use LD_LIBRARY_PATH in any way.
[ That's good! ]
Still, let's try to execute testB: it does not work!!! The -rpath is
used only by the linker, not by the loader!
**************************
To sum up: Xavier decided to use the -rpath trick to avoid setting
LD_LIBRARY_PATH when linking. Instead he hard-coded the stublibs
directory in the produced code, so that the loader does not complain.
One trick is for the linker, the other one for the loader.
The second trick works only for the stublibs directory. The first one
always work (but makes lintian complain). Moreover there is also the
symbolic link trick from dllname.so to libname.so that should be done
by hand.
What happens if you remove the -rpath from a debian package? You may
break the compilation processes of other people that are expecting
your library to have the -rpath and that do not have the LD_LIBRARY_PATH
set to stublibs (or other strange directories).
Final note: of course the problem solved by rpath was much more critical
_before_ the introduction of the single stublib directory (those times
when my LD_LIBRARY_PATH used to be several lines long).
I hope that all this could be useful to somebody: my wirst is aching!
Cheers,
C.S.C.
--
----------------------------------------------------------------
Real name: Claudio Sacerdoti Coen
PhD Student in Computer Science at University of Bologna
E-mail: sacerdot@cs.unibo.it
http://www.cs.unibo.it/~sacerdot
----------------------------------------------------------------
Attachment:
rpath.tgz
Description: GNU Unix tar archive