[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: ocaml compiled binaries and rpath



On Fri, Apr 11, 2003 at 06:26:01PM +0200, Claudio Sacerdoti Coen wrote:
> > 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...

Sorry for the late reply, but i just now had time to read it.

>  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

This is just your executable not finding the dlla.so lib. Normal, since
you didn't tell ocamlrun where to find it, using the ld.conf file.

And anyway, we have reached a consensus with upstream on this, and
LIBDIR/stublibs is the standard directory to put stublibs. debian ocaml
packages scan /usr/local/lib/ocaml/3.06/stublibs in addition.

>  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. ]

No, you have to set the path in /usr/lib/ocaml/3.06/ld.conf.

>  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 ]

Mmm, ...

>  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.

Well, the problem as i see it, is that in the case lintian complains, it
is usually about libraries in the /usr/lib or /usr/X11R6/lib directory.
As these are standard directories, no rpath is needed, and it can be
safely removed.

I think the rpath is there for cases where you install ocaml all
over the place, and not for the debian case, where we know exactly where
everything goes, as mandated by the policy.

>  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).

No, because there is the ocaml ld.conf, and because i believe that we
don't handle dll.so files directly, but only in conjunction with the
corresponding .cmos, which contain the necessary information.

In fact, in the case of the planet _executable_, it is not a library,
but a native code exectuable, i believe the rpath is pulled in by the
labltk library.

>  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).

Not sure, before the stublib directory was standardized, we used a
mechanism in debian so that each library providing package called a
script which added the directory the stublib was in to the ld.conf file,
and also a way for a user to add such directories manually also.

Now, local installed ocaml stuff should put the stublibs into
/usr/local/lib/ocaml/<ver>/stublibs, and packages install it into
/usr/lib/ocaml/<ver>/stublibs and there is no such problems.

>  I hope that all this could be useful to somebody: my wirst is aching!

:)))

But i am still not really convinced, at least in the debian case.

Friendly,

Sven Luther



Reply to: