Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Inline::C external library linking problem

by whakka (Hermit)
on Apr 03, 2009 at 23:59 UTC ( [id://755374]=perlquestion: print w/replies, xml ) Need Help??

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

Hi Monks,

I need to use libtiff and libgeotiff so I'm embeding C in a Perl program and gluing it together with Inline::C.

The C code compiles fine using gcc (version 4.1.2 20080704 (Red Hat 4.1.2-44)) and the normal -l flags (-ltiff -lgeotiff -lm) but I'm having trouble setting up the library linkages when configuring Inline::C.

While I'm not entirely sure what's going on, libtiff is located in /usr/lib while libgeotiff was installed by the sysadmin in /usr/local/lib (with header files in /usr/local/include). Everything works fine when I just use libtiff, but when I specify the LIB directive to use libgeotiff also I get the compiler error:

Had problems bootstrapping Inline module 'inline04b_pl_8926' Can't load '.../_Inline/lib/auto/inline04b_pl_8926/inline04b_pl_8926.s +o' for module inline04b_pl_8926: libgeotiff.so: cannot open shared ob +ject file: No such file or directory at /usr/lib64/perl5/5.8.8/x86_64 +-linux-thread-multi/DynaLoader.pm line 230. at /usr/lib/perl5/site_perl/5.8.8/Inline.pm line 504

No amount of permutations of these options gives me any better results. The following code illustrates the problem pared down:

#!/usr/local/bin/perl use warnings; use strict; my $img = shift || die "Usage: perl inline.pl [tiff]\n"; my $gtif = 0; if ( ! $gtif ) { die "Couldn't use $img\n" unless use_tiff( $img ); tiff_cleanup(); } else { die "Couldn't use $img\n" unless use_gtif( $img ); gtif_cleanup(); } #--------------------------------------------------------------------- +------------------------------ use Inline C => Config => LIBS => '-lm -ltiff -L/usr/local/lib -lgeotiff', # LIBS => '-lm -ltiff', # Works with $gtif = 0 INC => '-I/usr/local/include' ; use Inline C => <<'END_OF_C_CODE'; #include <stdio.h> #include <stdlib.h> #include <tiff.h> #include "geotiff.h" #include "xtiffio.h" #define DEBUG 1 TIFF *IMAGE; // TIFF image handle GTIF *GEO_IMAGE; // GeoTIFF image handle void check_image(TIFF *image) { // Check that it is of a type that we support - if not throw error +s uint16 bps, spp; if ( (TIFFGetField(image, TIFFTAG_BITSPERSAMPLE, &bps) == 0) || (b +ps != 8) ) throw_error("Either undefined or unsupported number of bits pe +r sample.\n"); if ( (TIFFGetField(image, TIFFTAG_SAMPLESPERPIXEL, &spp) == 0) || +(spp != 1) ) throw_error("Either undefined or unsupported number of samples + per pixel.\n"); if ( TIFFIsTiled(image) == 0 ) throw_error("Image must be tiled.\n"); } int use_tiff( const char *image_file ) { if ( DEBUG == 1 ) printf( "TIFF file: %s\n", image_file ); // Open the TIFF image if ( (IMAGE = TIFFOpen(image_file, "r")) == NULL ) { throw_error("Could not open incoming image.\n"); } check_image(IMAGE); return 1; } int use_gtif( const char *image_file ) { if ( DEBUG == 1 ) printf( "GTIF file: %s\n", image_file ); // Open the TIFF image if ( (IMAGE = XTIFFOpen(image_file, "r")) == NULL ) { throw_error("Could not open incoming image.\n"); } check_image(IMAGE); // Open the geotiff information handle on image if ( (GEO_IMAGE = GTIFNew(IMAGE)) == NULL ) throw_error("Could not read geotiff data on image.\n"); return 1; } void tiff_cleanup() { TIFFClose(IMAGE); } void gtif_cleanup() { GTIFFree(GEO_IMAGE); XTIFFClose(IMAGE); } void throw_error(char * msg) { fprintf(stderr,msg); exit(42); } END_OF_C_CODE

Full output:

<-----------------------Information Section--------------------------- +--------> Information about the processing of your Inline C code: Your source code needs to be compiled. I'll use this build directory: /.../_Inline/build/inline04b_pl_8926 and I'll install the executable as: /.../_Inline/lib/auto/inline04b_pl_8926/inline04b_pl_8926.so The following Inline C function(s) have been successfully bound to Per +l: void gtif_cleanup() void test() void throw_error(char * msg) void tiff_cleanup() int use_gtif(const char * image_file) int use_tiff(const char * image_file) <-----------------------End of Information Section-------------------- +--------> Starting Build Preprocess Stage Finished Build Preprocess Stage Starting Build Parse Stage Finished Build Parse Stage Starting Build Glue 1 Stage Finished Build Glue 1 Stage Starting Build Glue 2 Stage Finished Build Glue 2 Stage Starting Build Glue 3 Stage Finished Build Glue 3 Stage Starting Build Compile Stage Starting "perl Makefile.PL" Stage Writing Makefile for inline04b_pl_5b15 Finished "perl Makefile.PL" Stage Starting "make" Stage /usr/bin/perl /usr/lib/perl5/5.8.8/ExtUtils/xsubpp -typemap /usr/lib/ +perl5/5.8.8/ExtUtils/typemap inline04b_pl_5b15.xs > inline04b_pl_5b +15.xsc && mv inline04b_pl_5b15.xsc inline04b_pl_5b15.c gcc -c -I... -I/usr/local/include -D_REENTRANT -D_GNU_SOURCE -fno-str +ict-aliasing -pipe -Wdeclaration-after-statement -I/usr/local/include + -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -O2 - +g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector +--param=ssp-buffer-size=4 -m64 -mtune=generic -DVERSION=\"0.00\" -D +XS_VERSION=\"0.00\" -fPIC "-I/usr/lib64/perl5/5.8.8/x86_64-linux-thre +ad-multi/CORE" inline04b_pl_5b15.c Running Mkbootstrap for inline04b_pl_5b15 () chmod 644 inline04b_pl_5b15.bs rm -f blib/arch/auto/inline04b_pl_5b15/inline04b_pl_5b15.so gcc -shared -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions - +fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic inline +04b_pl_5b15.o -o blib/arch/auto/inline04b_pl_5b15/inline04b_pl_5b15. +so \ -lm -ltiff -L/usr/local/lib -lgeotiff \ chmod 755 blib/arch/auto/inline04b_pl_5b15/inline04b_pl_5b15.so cp inline04b_pl_5b15.bs blib/arch/auto/inline04b_pl_5b15/inline04b_pl_ +5b15.bs chmod 644 blib/arch/auto/inline04b_pl_5b15/inline04b_pl_5b15.bs Finished "make" Stage Starting "make install" Stage Installing .../_Inline/lib/auto/inline04b_pl_5b15/inline04b_pl_5b15.so Installing .../_Inline/lib/auto/inline04b_pl_5b15/inline04b_pl_5b15.bs Files found in blib/arch: installing files in blib/lib into architectu +re dependent library tree Writing .../_Inline/lib/auto/inline04b_pl_5b15/.packlist Finished "make install" Stage Starting Cleaning Up Stage Finished Cleaning Up Stage Finished Build Compile Stage Had problems bootstrapping Inline module 'inline04b_pl_5b15' Can't load '.../_Inline/lib/auto/inline04b_pl_5b15/inline04b_pl_5b15.s +o' for module inline04b_pl_5b15: libgeotiff.so: cannot open shared ob +ject file: No such file or directory at /usr/lib64/perl5/5.8.8/x86_64 +-linux-thread-multi/DynaLoader.pm line 230. at /usr/lib/perl5/site_perl/5.8.8/Inline.pm line 504 at inline04b.pl line 53 BEGIN failed--compilation aborted at inline04b.pl line 171.

I really appreciate any assistance, thanks.

Update: Thanks to all the very excellent and educational replies, especially almut whose prescient suggestion to replace -L/usr/local/lib -lgeotiff with MYEXTLIB => '/usr/local/lib/libgeotiff.a' did the trick for reasons explained.

Replies are listed 'Best First'.
Re: Inline::C external library linking problem
by almut (Canon) on Apr 04, 2009 at 04:40 UTC

    The compiler option -L/usr/local/lib does not automatically add the path to the list of runtime library search paths. It only makes the library be found at compile time.  Unless /usr/local/lib is otherwise configured to be searched by the dynamic linker, the shared library won't be found at runtime (which seems to be the problem in your case).

    The runtime library search paths are normally set using the linker option -rpath, or the environment variable LD_RUN_PATH (at compile time).

    That's where MakeMaker comes in (or should). Normally, it would take care of setting the appropriate LD_RUN_PATH when it sees something like LIBS => ['-L/usr/local/lib -lgeotiff'].  In the generated Makefile you should find definitions like

    # See ExtUtils::Liblist for details # EXTRALIBS = -L/usr/local/lib -lgeotiff LDLOADLIBS = -L/usr/local/lib -lgeotiff BSLOADLIBS = LD_RUN_PATH = /usr/local/lib

    which would then prepend LD_RUN_PATH="/usr/local/lib" to the gcc -shared ... -L/usr/local/lib -lgeotiff command line.  I'm not sure why this isn't happening in your case.

    In addition to adding /usr/local/lib to LD_LIBRARY_PATH (which is ugly, as it always needs extra fiddling at runtime), you could try the following workarounds:

    (1) specify the appropriate -rpath yourself. For this, you'd need to somehow get -Wl,-rpath=/usr/local/lib into the link command. This isn't quite as easy as you might think, because Inline::C's LDDLFLAGS option doesn't allow adding to it, so you'd need to re-specify all other options, which you typically wouldn't know, as they are being auto-configured...  What does seem to work, though, is misusing the LD option, by setting

    LD => 'gcc -Wl,-rpath=/usr/local/lib'

    (which did create the appropriate linker command line, for me)

    (2) In case you also have a static library libgeotiff.a, you could link against that one, in which case you wouldn't have any additional runtime dependencies (the static lib would need to have been compiled with -fPIC, though, because it will be linked with a shared lib).  If you have both shared (.so) and static (.a) versions in /usr/local/lib, you'd need to move away the shared one, because gcc defaults to using the shared lib, if found. Alternatively, specify the full path to the .a file directly via MYEXTLIB (instead of -L/usr/local/lib -lgeotiff), i.e.

    MYEXTLIB => '/usr/local/lib/libgeotiff.a'
      Hi I am facing an error in Cygwin, when I run Perl scripts which talks to DLL files Laptop specification: HP Elite book Model – 8540W Intel i5 64 bit processor Win XP OS Software – Cygwin Additional modules – Inline & Parse Rec descent. My Perl installation in Cygwin is done properly, I am sure about that (I ran some simple “hello world” kind of scripts & that is working fine). I checked the installation of Inline & Parse Rec Descent it has installed it properly. I checked this using “make test” script, I get all the tests are passing in both Inline & Parse Rec descent. When I run Perl scripts which uses DLL files I get this error, Please see the error below. MY Perl scripts uses *.PM Perl modules which talks to DLL files of a particular hardware. As per the error below it couldn’t find some the files at run time or compiling stage, however, I checked it all the required files are present in the _Inline folder. I don’t understand why it couldn’t load it at run time or compile time….! This is the error. Had problems bootstrapping Inline module 'Corelis_JTAG_6bd5' Can't load '/cygdrive/c/test/_Inline/lib/auto/Corelis_JTAG_6bd5/Corelis_JTAG_6bd 5.dll' for module Corelis_JTAG_6bd5: No such file or directory at /usr/lib/perl5 /5.8/cygwin/DynaLoader.pm line 230. at /usr/lib/perl5/site_perl/5.8/Inline.pm line 500 at Corelis_JTAG.pm line 25 BEGIN failed--compilation aborted at Corelis_JTAG.pm line 25. Compilation failed in require at ./crm_bist.pl line 33. BEGIN failed--compilation aborted at ./crm_bist.pl line 33. Moreover, the same Cygwin installation, Inline version, Parse Rec descent is done the same way in other two IBM Desktops & one TOSHIBA laptop. There is literally no difference between the scripts & installation in other PC's. However, the new laptop I am trying is not going through & it throughs me the above error. But, in my IBM PC & Toshiba laptop works fine. The new laptop which is not working is HP Elite book 8540W with SATA SSD hard disk. This leaves me to suspect two things. 1. The OS (Win XP) version or installation problem!!!!!! (The Win XP in the desktop & laptop is about 5 years old version of Win XP - I don't know what would help there to you to debug this..) 2. The hard disk in IBM desktop is IDE & the one in Toshiba laptop is SATA2!!!!. The new laptop which is not working is HP Elite book 8540W with SATA SSD hard disk. Does hard disk matters for Cygwin at all.. Do you think the above two reasons would make anything to fail in Cygwin, what dependencies they have with respect to Cygwin. Please help. Shasi
Re: Inline::C external library linking problem
by syphilis (Archbishop) on Apr 04, 2009 at 00:49 UTC
    Hi whakka ,

    I think it's just that libgeotiff.so is not being found by default. Maybe the location of libgeotiff.so needs to be added to LD_LIBRARY_PATH (or something like that ... I'm a bit hazy on these nixy details :-).

    Cheers,
    Rob
Re: Inline::C external library linking problem
by ig (Vicar) on Apr 04, 2009 at 04:28 UTC

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://755374]
Approved by almut
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others contemplating the Monastery: (5)
As of 2024-04-18 00:16 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found