Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi monks,

I want to be able to use Perl 5.10.0 on both Linux and Solaris boxes, and have successfully built it on both - however, I wish to be able to use it relocatable, and the Solaris binary does not seem to work as expected. The Linux binary searches for library paths (../lib) from the binary install dir, however the Solaris binary just searches from the current path.

To build perl on each box I used:
./Configure -de -Dprefix=/home/user/perl -Dcc=gcc -Duserelocatableinc make make install

I've checked the binaries, and both refer to library paths using '.../../lib', so in theory they both should be fully relocatable, so my question is this: Does any one know of any problems with building a properly relocatable perl on Solaris?

Below I've posted the perl -V from both binaries (for what it's worth). There ARE differences in the boxes environments, and I'm hoping that I've been a muppet and just not included a required library in the Solaris build.

Linux (relocates from binary install path - as expected):
Summary of my perl5 (revision 5 version 10 subversion 0) configuration +: Platform: osname=linux, osvers=2.6.9-22.0.1.elsmp, archname=x86_64-linux uname='linux linbox.domain.com 2.6.9-22.0.1.elsmp #1 smp tue oct 1 +8 18:39:02 edt 2005 x86_64 x86_64 x86_64 gnulinux ' config_args='-de -Dprefix=/home/user/perl -Duserelocatableinc -Dcc +=gcc' hint=recommended, useposix=true, d_sigaction=define useithreads=undef, usemultiplicity=undef useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=und +ef use64bitint=define, use64bitall=define, uselongdouble=undef usemymalloc=n, bincompat5005=undef Compiler: cc='gcc', ccflags ='-fno-strict-aliasing -pipe -I/usr/local/includ +e -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64', optimize='-O2', cppflags='-fno-strict-aliasing -pipe -I/usr/local/include' ccversion='', gccversion='3.2.3 20030502 (Red Hat Linux 3.2.3-47.3 +)', gccosandvers='' intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678 d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=1 +6 ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', + lseeksize=8 alignbytes=8, prototype=define Linker and Libraries: ld='gcc', ldflags =' -L/usr/local/lib' libpth=/usr/local/lib /lib /usr/lib /lib64 /usr/lib64 /usr/local/l +ib64 libs=-lnsl -ldl -lm -lcrypt -lutil -lc perllibs=-lnsl -ldl -lm -lcrypt -lutil -lc libc=/lib/libc-2.3.4.so, so=so, useshrplib=false, libperl=libperl. +a gnulibc_version='2.3.4' Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E' cccdlflags='-fPIC', lddlflags='-shared -O2 -L/usr/local/lib' Characteristics of this binary (from libperl): Compile-time options: PERL_DONT_CREATE_GVSV PERL_MALLOC_WRAP USE_64_ +BIT_ALL USE_64_BIT_INT USE_LARGE_FILES USE_PERLIO Built under linux Compiled at Apr 25 2008 16:38:21 @INC: /home/user/perl/lib/5.10.0/x86_64-linux /home/user/perl/lib/5.10.0 /home/user/perl/lib/site_perl/5.10.0/x86_64-linux /home/user/perl/lib/site_perl/5.10.0 .

Solaris (relocates from ./):
Summary of my perl5 (revision 5 version 10 subversion 0) configuration +: Platform: osname=solaris, osvers=2.8, archname=sun4-solaris uname='sunos solbox.domain.com 5.8 generic_117350-43 sun4u sparc s +unw,sun-fire-480r ' config_args='-de -Dprefix=/home/user/perl -Dcc=gcc -Duserelocatabl +einc' hint=recommended, useposix=true, d_sigaction=define useithreads=undef, usemultiplicity=undef useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=und +ef use64bitint=undef, use64bitall=undef, uselongdouble=undef usemymalloc=n, bincompat5005=undef Compiler: cc='gcc', ccflags ='-fno-strict-aliasing -pipe -D_LARGEFILE_SOURCE + -D_FILE_OFFSET_BITS=64', optimize='-O', cppflags='-fno-strict-aliasing -pipe' ccversion='', gccversion='3.3.2', gccosandvers='solaris2.8' intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=4321 d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=1 +6 ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', + lseeksize=8 alignbytes=8, prototype=define Linker and Libraries: ld='gcc', ldflags =' -L/usr/local/lib ' libpth=/usr/local/lib /usr/lib /usr/ccs/lib libs=-lsocket -lnsl -ldl -lm -lc perllibs=-lsocket -lnsl -ldl -lm -lc libc=/lib/libc.so, so=so, useshrplib=false, libperl=libperl.a gnulibc_version='' Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags=' ' cccdlflags='-fPIC', lddlflags='-G -L/usr/local/lib' Characteristics of this binary (from libperl): Compile-time options: PERL_DONT_CREATE_GVSV PERL_MALLOC_WRAP USE_LARGE_FILES USE_PERLIO Built under solaris Compiled at May 15 2008 13:00:27 @INC: ./../lib/5.10.0/sun4-solaris ./../lib/5.10.0 ./../lib/site_perl/5.10.0/sun4-solaris ./../lib/site_perl/5.10.0 .

Thanks,
CK.

Replies are listed 'Best First'.
Re: Relocatable Perl 5.10.0 on Solaris
by Corion (Patriarch) on May 16, 2008 at 09:37 UTC

    I'm confused. Either you mean something with "relocatable" that's different from what I mean, or I'm not understanding your configuration.

    Your Linux configuration uses absolute directories for its @INC. This means that you can launch perl from any directory and it will find its libraries. But this also means that you cannot move perl or its directories to any other place. So, in my opinion, the Linux perl is not relocatable.

    Your Solaris configuration uses relative directories for its @INC. This means that you can only launch perl from a directory where ../lib points to the Perl libraries. This also means that you can move perl around wherever you want to, as long as you invoke it from a directory in the right relative position. In this case, the Solaris perl is somewhat relocatable.

    I think Unixish operating systems have a problem with determining the directory where an executable lives in and hence it's not really supported for a program to find out the directory it is living in to determine the place of library directories in relation to that path.

      I think Unixish operating systems have a problem with determining the directory where an executable lives in and hence it's not really supported for a program to find out the directory it is living in to determine the place of library directories in relation to that path.

      ...but I think that's how it's meant to work, if I'm reading the docs correctly (from perl5100delta.pod):

      Relocatable installations

      There is now Configure support for creating a relocatable perl tree. If you Configure with -Duserelocatableinc, then the paths in @INC (and everything else in %Config) can be optionally located via the path of the perl executable.

      That means that, if the string ".../" is found at the start of any path, it's substituted with the directory of $^X. So, the relocation can be configured on a per-directory basis, although the default with -Duserelocatableinc is that everything is relocated. The initial install is done to the original configured prefix.

      So, I'd say the OP's expectations are at least somewhat legitimate :)

        Ah hah - so maybe the issue is that the Solaris @INC does not contain .../ but ./../, at least to what the OP showed us. So either the Perl was configured wrong or the configure process went wrong somewhere. Maybe patching the resulting binary is the easiest way out, as the string only decreases in length which can easily be fixed by zero padding it at the end.

      Nicholas Clark applied for a grant to fix this, i don't know if he has :)
      Thanks for your quick response...

      To clarify - they are BOTH built with -Duserelocatableinc, which (according to the perl 5.10.0 docs) should make them relocatable. @INC paths reported by the -V flag are as you say fixed and relative respectively, however they are resolved to this at run time. Within the binary they are stored as .../../lib etc... So what seems to be happening is that the Linux binary resolves ... to the binary path (in this case /home/user/bin) and the Solaris binary resolves ... to the current path (.).

      The Linux binary definitely is relocatable. If I rename the install dir it still works (provided it's found in the PATH of course).

      Regards,
      CK.
Re: Relocatable Perl 5.10.0 on Solaris
by almut (Canon) on May 16, 2008 at 12:06 UTC

    FWIW, I can confirm that $^X isn't working properly on Solaris.

    It seems that - on Linux - the path to the executable is determined via /proc/self/exe1. At least that's the impression I get from a quick look at the source, as well as the strace output of perl -e 'print "$^X\n"'.  Unfortunately, Solaris doesn't seem to have /proc/self/exe.

    A little digging shows that - on Solaris (10) - something like

    $ perl -e 'printf "%s\n", readlink "/proc/self/path/a.out"' /usr/local/perl-5.8.4/bin/perl

    may have a better chance to provide the info that the symlink /proc/self/exe holds on Linux... (on this Solaris box, I currently don't have Perl-5.10, so I tested with an older version — the $^X mechanism doesn't seem to have changed much since, anyway).

    (might do some more thorough digging later... as time permits — in which case I'll update the node)

    ___

    1 in case you want to look at the respective code fragments yourself, grep for one of S_set_caret_X, S_procself_val, PROCSELFEXE_PATH, HAS_PROCSELFEXE.

    ___

    Update: (Note to the OP) In case the /proc/self/path/a.out symlink is working for you, too, you could try to extend the Configure script here (line 15563):

    procselfexe='' val="$undef" case "$d_readlink" in "$define") if $issymlink /proc/self/exe ; then $ls -l /proc/self/exe > reflect if $contains /`basename $ls` reflect >/dev/null 2>&1; then echo "You have Linux-like /proc/self/exe." procselfexe='"/proc/self/exe"' val="$define" fi fi ...

    and see if it works then...

      Unfortunately, the box is solaris 8, not 10 - and there doesn't seem to be a /proc/self/path/a.out symlink.

      I haven't (so far) been able to find anything I could use in place of /proc/self/exe either.

      Thanks for you help so far almut, I have to say I'm finding the level of support here outstanding.

        Unfortunately, the box is solaris 8, not 10 ...

        I was afraid you were going to say that :) — in this case you're essentially out of luck...

        On anything older than Solaris 10, the proc filesystem is rather limited. AFAIK, the only info remotely similar to /proc/self/exe (or /proc/self/path/a.out for that matter), is in /proc/self/auxv (aux vector — a binary structure), but it's not really the same, in particular on Solaris 8 (things have gotten somewhat better starting with Solaris 9).

        If you're really determined, you could try to hack up something based on the standard C library functions getexecname, which extracts the appropriate structure from /proc/self/auxv, together with realpath, which resolves all "..", "." and symbolic links in a path (, and possibly also getcwd).

        One ugly problem with getexecname on Solaris 8 is that it doesn't make a distinction between an executable script and its associated interpreter invoked via the shebang line. For example, with the following naive snippet

        #include <stdlib.h> #include <limits.h> #include <stdio.h> int main() { const char *execname; char *execpath; char pathbuf[PATH_MAX]; execname = getexecname(); execpath = realpath(execname, pathbuf); printf("execname: %s\n", execname); printf("realpath: %s\n", execpath); }

        if you compile this with cc foo.c -o foo and put the resulting binary in - let's say - /home/ck/bin/, and then create a dummy script bar with the shebang line #!/home/ck/bin/foo in some other directory like /home/ck/myscripts/, and call it from there, you'd get on Solaris 8:

        $ ./bar execname: bar realpath: /home/ck/myscripts/bar

        while on Solaris 9 or 10, the execname would be more useful

        $ ./bar execname: /home/ck/bin/foo realpath: /home/ck/bin/foo

        You see the problem with Solaris 8 — and this is not the only one...

        (note that the code would of course have to be linked into perl (to set $^X), i.e. the foo in the example represents the Perl binary)

      IIRC, this type of problem is also happens with $0 in simple shell scripts. On some systems $0 is just the base file name, in others it's an absolute path to the script.

      FYI, you can get the thing to work if you use the full path to the perl:

      $ type perl perl is /usr/local/test/perl/bin/perl $ perl -e 'print "$^X\n"' perl $ /usr/local/test/perl/bin/perl -e 'print "$^X\n"' /usr/local/test/perl/bin/perl

      So a shell script wrapper might also be a workaround, to set up an environment where the full path is used.

      More to the point, is there a fix for this, yet?

      Thanks, Bob

Re: Relocatable Perl 5.10.0 on Solaris
by Anonymous Monk on May 16, 2008 at 09:50 UTC

    Check the top of Config.pm in both distros. One may have rel links and the other absolute links. Just a guess.