http://qs321.pair.com?node_id=637630


in reply to static linking demanded

Static linking is almost never the answer, but there is one exception which is if you need bindings to an external system that somehow does not give you position-independent code. An example for many years was arsperl.

If you want to go with static linking then ysth's post is the answer.

If a system does not support dynamic loading (Is SCO really like this? -- that would IMHO almost qualify as a dinosaur-OS ;), I believe that any XS glue must be compiled statically. If the glue needs shared libraries then they will be called "statically" by the system dynamic loader (at executable startup time usually, but compiler flags can normally enable some on-demand mode) in the usual way i.e the way the system will load the libc shared library.

Still you have another option: Build a perl with all dependencies inside the distribution tree. I have been doing that for years on HP-UX.

  • First you pick you path: say PREFIX=/var/tmp/p/opt/perl588. This is my "main" PREFIX.
  • Put all your extlibs below $PREFIX/ext say. each extlib in its own dir. In general you'll have {extlib}/inc and {extlib}/lib.
  • Build perl. note that you can currently build once, deploy many i.e have make install say write in /var/tmp/p/opt/perl588 and also /opt/perl588 for example.
  • Build all your external modules. Any build should point at libraries in $PREFIX/ext (say your own libexpat and libxml2 etc...).
  • Check that the previous claim is true. On HP-UX you can use chatr; on others ldd is your friend; on cygwin you'll use cygcheck etc. You are the one in control here: it's you who defines if a library is external or internal to your distribution. (As an example you might like to include say 3 differents versions of oracle client libraries, working with different copies of DBD::Oracle, each one with the right glue! -- and tell me then if 'no ...;' really works;).
  • You have to repeat the process for any client path where you plan to have perl+modules installed. Yes this involves rebuilding all the modules...

    On HP-UX I use a dirty trick to speed up the process. suppose I built all my modules for /var/tmp/opt/perl588. I want them now for /opt/perl588. The install process takes care of the perl core. So for the modules I have to care about a few things:

  • shared libraries that depend on a library inside /var/tmp/opt/perl588/ext
  • special directories needed by a module. Here the solution is easy: just use a common path for all distribs (must not be contained in any final "PREFIX" dir.
  • I deal with the first point by direct (binary) subst on each shared object. I use perl of course ;) 'perl -0pi s{/var/tmp/p/opt/perl588}{///////////opt/perl588}' (or a variant setting a flag to modify only the first "line" seen)
  • binary grep for /var/tmp/p/perl588 just in case ;)

    The result is a tarrable perl dist that you can install almost anywhere (it has two parts the perl dir + special dirs needed by modules).

    Note that I do not like shared libraries with dependencies on other shared libraries. It is just too confusing. When I build my own shared libraries I try to avoid that. The responsability of knowing with what to link should be the responsability of the executable. Of course bindings are another matter.

    Nicholas Clark did some work on making perl more relocatable (IIRC was done after 5.8.8). You can browse the p5p archives to see the details.

    cheers --stephan

    P.S there might be licensing issues...

  • Replies are listed 'Best First'.
    Re^2: static linking demanded
    by bkchapin (Acolyte) on Sep 10, 2007 at 14:51 UTC
      What I've heard is SCO does not have libdl or some equivalent. So, no dlopen library function. SCO still has some sort of dynamic linking, just not that kind.

      Took me a moment to understand that dirty trick with the library directory, and yeah, that's pretty cool, sneaky, and dirty. The crucial point is that the length of the directory name is kept the same by padding the front of the name with the correct number of '/' characters. Sort of the NOP of directory names.

        A dirty hack for sure. On cygwin and possibly others you might have to use /. instead of // as // might indicate some network share. Devious things can even be done to defeat checksum schemes.

        Dynamic linking is really when you can load at runtime a shared library; this is what perl needs for "use ...;". What is given by a "dynamic linker" like dld (/usr/lib/dlds.so for example) and the such is actually pretty static. The terminology varies a lot with the O.S. True dynamic linking is when a program can use the same API as the "dynamic linker". In perl code the true dynamic nature of a dlopen-like API means you can "use" to load and "no" to unload; this can be useful if you need to maintain a low memory consumption profile (using "use" and "no" as many times as necessary). Note that a process will not give back to the O.S the memory once taken but it can certainly reuse.

        cheers --stephan