Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

DynaLoader can't resolve multiple Linux shared objects

by boleary (Beadle)
on Nov 14, 2018 at 13:29 UTC ( #1225782=perlquestion: print w/replies, xml ) Need Help??

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

I have created a module LicenseInterface.pm built with SWIG. LicenseInterface.so references 2 other shared objects libLicIntfcLib.so and llibmgr11.so which I am including in the auto/LicenseInterface directory.

I cannot get it to load properly for my end application where I am trying to use ActiveState PerlApp to distribute the code as a pre-packaged Linux .exe file (but it works fine in Windows)

use strict; use warnings; push @INC,"lib"; require LicenseInterface; print "LicenseInterface got loaded\n";

Here is the lib directory structure

test.pl |--lib\ |--LicenseInterface.pm |--auto\ |--LicenseInterface\ |--LicenseInterface.bs (added this to try to influence @dl_resolv +e_using) |--LicenseInterface.so |--libLicIntfcLib.so |--llibmgr11.so

Here is the ldd report for the shared objects (without LD_LIBRARY_PATH set)

[boleary@new-host testLib]$ ldd auto/LicenseInterface/LicenseInterface +.so linux-gate.so.1 => (0x00f36000) libLicIntfcLib.so => not found ****This is the .so that dynaload +er can't resolve*** libperl.so => not found ###BUT THIS ONE gets resolved!!! libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00508000) libm.so.6 => /lib/libm.so.6 (0x00331000) libc.so.6 => /lib/libc.so.6 (0x00ac4000) /lib/ld-linux.so.2 (0x002c3000) libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00ed9000) [boleary@new-host testLib]$ ldd auto/LicenseInterface/libLicIntfcLib.s +o linux-gate.so.1 => (0x0025c000) liblmgr11.so => not found ****This is the other .so that dynaload +er can't resolve*** libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00682000) libm.so.6 => /lib/libm.so.6 (0x00ce7000) libc.so.6 => /lib/libc.so.6 (0x00d40000) /lib/ld-linux.so.2 (0x002c3000) libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00143000)

When I use or require LicenseInterface.pm, the DynaLoader bootstrap code cannot resolve the libLicIntfcLib.so (and the llibmgr11.so) (I set PERL_DL_DEBUG to 1 before running to get more info)

DynaLoader.pm loaded (/opt/ActivePerl-5.18/site/lib /opt/ActivePerl-5. +18/lib . lib, /lib /usr/lib /usr/local/lib) DynaLoader::bootstrap for LicenseInterface (auto/LicenseInterface/Lice +nseInterface.so) Can't load './auto/LicenseInterface/LicenseInterface.so' for module Li +censeInterface: libLicIntfcLib.so: cannot open shared object file: No + such file or directory at /opt/ActivePerl-5.18/lib/DynaLoader.pm lin +e 191.

I can easily fix the problem if I add the hard path: "auto/LicenseInterface" to the LD_LIBRARY_PATH in the env I am running perl from

export LD_LIBRARY_PATH=./auto/LicenseInterface [boleary@new-host testLib]$ perl test_simple.pl DynaLoader.pm loaded (/opt/ActivePerl-5.18/site/lib /opt/ActivePerl-5. +18/lib . lib, /lib /usr/lib /usr/local/lib ./auto/LicenseInterface) DynaLoader::bootstrap for LicenseInterface (auto/LicenseInterface/Lice +nseInterface.so) LicenseInterface got loaded

The trouble with this is that I am using perlapp from ActiveState to try and build and distribute a working .exe file, and I do not have any control over LD_LIBRARY_PATH in that case (and I know that perlApp is no longer supported)

On a windows system, (where I started this adventure) DynaLoader has no trouble resolving the referenced sharedObjects with LicenseInterface.dll, libLicIntfcLib.dll and llibmgr11.dll and the perlApp .exe file works perectly

I tried a couple of tricks.. Firt I tried to the ./auto/LicenseInterface to the LD_LIBRARY_PATH inside test.pl

BEGIN { $ENV{LD_LIBRARY_PATH}.="./auto/LicenseInterface"; } use strict; use warnings; push @INC,"lib"; require LicenseInterface; print "LicenseInterface got loaded\n"; exit
perl test_simple1.pl DynaLoader.pm loaded (/opt/ActivePerl-5.18/site/lib /opt/ActivePerl-5. +18/lib . lib, /lib /usr/lib /usr/local/lib ./auto/LicenseInterface) DynaLoader::bootstrap for LicenseInterface (auto/LicenseInterface/Lice +nseInterface.so) Can't load './auto/LicenseInterface/LicenseInterface.so' for module Li +censeInterface: libLicIntfcLib.so: cannot open shared object file: No + such file or directory at /opt/ActivePerl-5.18/lib/DynaLoader.pm lin +e 191. at lib/LicenseInterface.pm line 11. Compilation failed in require at test_simple1.pl line 8.

Here you can see that it added ./auto/LicenseInterface to the search path and that status line starting with "DynaLoader.pm loaded (" looks identical to the passing case above, but It still won't load it

Then I tried adding a LicenseInterface.bs file in the ./auto/LicenseInterface directory

push @dl_resolve_using=dl_findfile( qw( ./auto/LicenseInterface/libLicIntfcLib.so ./auto/LicenseInterface/liblmgr11.so ) );
perl test_simple1.pl DynaLoader.pm loaded (/opt/ActivePerl-5.18/site/lib /opt/ActivePerl-5. +18/lib . lib, /lib /usr/lib /usr/local/lib ./auto/LicenseInterface) DynaLoader::bootstrap for LicenseInterface (auto/LicenseInterface/Lice +nseInterface.so) BS: ./auto/LicenseInterface/LicenseInterface.bs (linux, dl_dlopen.xs) dl_findfile(./auto/LicenseInterface/libLicIntfcLib.so ./auto/LicenseIn +terface/liblmgr11.so) dl_findfile found: ./auto/LicenseInterface/libLicIntfcLib.so ./auto/Li +censeInterface/liblmgr11.so Can't load './auto/LicenseInterface/LicenseInterface.so' for module Li +censeInterface: libLicIntfcLib.so: cannot open shared object file: No + such file or directory at /opt/ActivePerl-5.18/lib/DynaLoader.pm lin +e 191. at lib/LicenseInterface.pm line 11. Compilation failed in require at test_simple1.pl line 8.

You can see that it actually found the other shared objects, but it still couldn't use them

It seems that DynaLoader cannot take advantage of the fact that I set LD_LIBRARY_PATH, so when it does its magic it must be limited to using the environment variables from the shell that started it. It is interesting to me that it can resolve the libperl.so

Does anyone have any ideas? Are there any known linux modules that are provided with multiple .so files that have worked around this before?

I can try to create one .so, with the other 2 .so libraries statically linked, but I am having trouble because I don't have total control over the llibmgr11 source.

Replies are listed 'Best First'.
Re: DynaLoader can't resolve multiple Linux shared objects
by Anonymous Monk on Nov 14, 2018 at 13:49 UTC
    Can you build libLicIntfcLib.so with $ORIGIN/auto/LicenseInterface in its rpath? $ORIGIN is a special prefix understood by GNU ld.so as "the directory where the executable resides". Or maybe you need to write just $ORIGIN without anything else because the current executable would be libLicIntfcLib.so and liblmgr11.so is already stored near it.

      I'm not sure how to do that, but will I look into it... That really sounds like what I need because this was just a simple test case and the module will not be located in such a convenient location

      So CLOSE! I added the:

      -Wl,-rpath,'$ORIGIN'

      to the g++ command like your helpful link told me... now it works when I run perl test.pl without LD_LIBRARY_PATH being set, and I can have the .so in ".' or './auto/LicenseInterface' or '../COMMON/auto/LicenseInterface'

      However, the perlApp exe file still does not work, but its the libperl.so that it can't find now, so it did resolve the libLicIntfcLib.so and liblmgr11.so files

      DynaLoader.pm loaded (../COMMON/LicenseInterface, /lib /usr/lib /usr/l +ocal/lib) DynaLoader::bootstrap for LicenseInterface (auto/LicenseInterface/Lice +nseInterface.so) Can't load 'auto/LicenseInterface/LicenseInterface.so' for module Lice +nseInterface: libperl.so: cannot open shared object file: No such fil +e or directory at /</home/boleary/git_repos/CE_TOOLS/testLib/BUILD_TE +MP/cadEnhance/tools/TESTLIB/testLib>DynaLoader.pm line 224. at /</home/boleary/git_repos/CE_TOOLS/testLib/BUILD_TEMP/cadEnhance/t +ools/TESTLIB/testLib>LicenseInterface.pm line 11.

        I did not need to link libperl !!!!

        now executable is working

        from hopeless to solved with one small hint! Thank you

Re: DynaLoader can't resolve multiple Linux shared objects
by ikegami (Pope) on Nov 14, 2018 at 17:56 UTC

    LD_LIBRARY_PATH has to be set before the process starts to be of any use.

    I'm not saying doing this will help you; I'm just saying it's not surprising what you did attempt did not work.

      Thanks ikegami! I figured that was the case with the LD_LIBRARY_PATH. Thankfully, the previous answer by anonymous monk suggesting I add the -rpath $ORIGIN in my linker command provided the solution I so desperately needed.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1225782]
Front-paged by haukex
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (4)
As of 2019-12-09 06:05 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?