10

I'm trying to compile an XS into perl [ed(ikegami): which is to say he's using ::MakeMaker's make perl to create a perl with a C vendor library statically linked in ] but when I do, the new version of perl does not support dynamic loading of modules. Any time I try to run perl code that has something like use Socket (or any other module), I get:

Can't load module Socket, dynamic loading not available in this perl.

Is there a compiler/linker switch I'm setting incorrectly or something? All of this was compiled back in 1998 and again in 2004 on a different box (hpux old on PA-RISC), but we're moving to a new box (hpux11 itanium) and I'm hitting the wall.

Here's is my Makefile.PL:

use ExtUtils::MakeMaker;
# See lib/ExtUtils/MakeMaker.pm for details of how to influence
# the contents of the Makefile that is written.
WriteMakefile(
    'NAME'      => 'Udtutil',
    'VERSION_FROM' => 'Udtutil.pm', # finds $VERSION
    'LIBS'      => '-L/usr/ud/PFUSION/Udtutil -L/usr/ud/lib -lapidummy ' .
                   '-lshare -ludsql -ludmach -lbasic ' .
                   '-lperf -lret1 -lides -lpipe -lfunc -lndx -lrep -lshm ' .
                   '-lmglm -lulc -lglm -ltpmem2 -lcmn ' .
                   '-llicn -ludus -lunix -lbci -lunirpc -lxmldl -leda ' .
                   '-lsslU2097e -lcryptoU2097e ' .
                   '-lodbc -lstd_v2 -lstream -lCsup -lpthread -lm -lcl ' .
                   '-ldld ' .
                   '-lnfaclnt -lodsdummy -lcl ' .
                   '-lCsup -lcl -lelf -lm -lcurses -lsec -lpam ',
    'INC'       => '-I/usr/ud/include',     # e.g., '-I/usr/include/other' 
    'OPTIMIZE'  => '-O -Ae +DD64 -q -z +u4 -w ',
    'LINKTYPE'  => 'dynamic',
    'OBJECT'    => '$(BASEEXT)$(OBJ_EXT) funchead.o interfunc.o callcf.o efs_init.o',
);

Here's my .xs file, Udtutil.xs

#ifdef __cplusplus
extern "C" {
#endif
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "/usr/ud/include/share.h"
#include "/opt/iibase/PFUSION/Udtutil/udtutil.h"
#ifdef __cplusplus
}
#endif

extern int U_IGNSIGSET;

extern int Iflags[2];

#if OS_NT

#define U_backsig(ignsigcnt) { if (((U_IGNSIGSET=(ignsigcnt)) == 0) && (Iflags[0] || Iflags[1])) U_sig_resend(); if (!U_IGNSIGSET && pU_sigflags && U_sigflags) NT_sig_kill(); }

#else

#define U_backsig(ignsigcnt) { if (((U_IGNSIGSET=(ignsigcnt)) == 0) && (Iflags[0] || Iflags[1])) U_sig_resend(); }

#endif

MODULE = Udtutil                PACKAGE = Udtutil

int startudt(value1,value2)
    int value1
    int value2

    CODE:
    int jmpret, sat;

    U_SET_JMP(jmpret,sat);
    if (jmpret) {
            /* proceed with initialization */
            udtcallbasic_init(value1,value2);
            RETVAL = 1;
    } else {
            /* shutdown unibasic and return unsuccessful value */
            udtcallbasic_done(1);
            RETVAL = 0;
    }

    OUTPUT:
    RETVAL

void stopudt(status)
    int status

    CODE:
    udtcallbasic_done(status);

void calludt(progname, argcount, ...)
    char * progname
    int argcount

    PPCODE:
    char * returnval;
    int paramspassed = 0;
    int status = 0;
    char ** arglist = NULL;
    int i;

    if (argcount + 2 == items) {
            /* build the C array from the Perl array */
            paramspassed = 1;
            arglist = (char **)malloc(argcount);
            for (i = 0; i < argcount; i++) {
                    arglist[i] = (char *)malloc(sv_len(ST(i+2))+1);
                    strcpy(arglist[i], SvPV(ST(i+2),PL_na));
            }

            /* make the call into the database */
            status = U_callbas(&returnval, progname, argcount, arglist);

            for (i = 0; i < argcount; i++) {
                    free(arglist[i]);
            }
            free(arglist);

            /* EXTEND(sp, 2); */
            XPUSHs(sv_2mortal(newSViv(paramspassed)));
            XPUSHs(sv_2mortal(newSViv(status)));

            if (status == 0) {
                    /* EXTEND(sp, 1); */
                    XPUSHs(sv_2mortal(newSVpv(returnval, 0)));
                    free(returnval);
            }
    } else {
            /* EXTEND(sp, 1); */
            XPUSHs(sv_2mortal(newSViv(paramspassed)));
    }

When I run perl Makefile.PL, everything looks good:

> perl Makefile.PL
Checking if your kit is complete...
Looks good
Writing Makefile for Udtutil
Writing MYMETA.yml

When I run make or make perl, everything goes well and it creates a new local perl binary.

However, when I execute ./perl mytest.pl, if mytest.pl *use*s any modules, I get:

Can't load module Socket, dynamic loading not available in this perl.

Any suggestions on how I can compile this new perl and still keep dynamic loading working?


ADDITIONAL INFO:

Here is config data from the old box (the one that works):

 > perl -V:usedl
 usedl='define';

 > perl -V
 Summary of my perl5 (5.0 patchlevel 4 subversion 4) configuration:   Platform:
     osname=hpux, osvers=10, archname=PA-RISC2.0
     uname='hp-ux autocrft b.10.20 u 9000893 341130351 unlimited-user license '
     hint=recommended, useposix=true, d_sigaction=define
     bincompat3=y useperlio=undef d_sfio=undef   Compiler:
     cc='cc', optimize='-O', gccversion=
     cppflags='-D_HPUX_SOURCE -Aa'
     ccflags ='-D_HPUX_SOURCE -Aa'
     stdchar='unsigned char', d_stdstdio=define, usevfork=false
     voidflags=15, castflags=0, d_casti32=define, d_castneg=define
     intsize=4, alignbytes=8, usemymalloc=y, prototype=define   Linker and Libraries:
     ld='ld', ldflags ='-L/usr/local/lib -L/usr/ud/lib'
     libpth=/usr/local/lib /usr/lib/pa1.1 /usr/ud/lib /lib /usr/lib /usr/ccs/lib
     libs=-lnet -lnsl_s -lndbm -ldld -lm -lc -lndir -lcrypt
     libc=/lib/libc.sl, so=sl
     useshrplib=false, libperl=libperl.a
     Dynamic Linking:
     dlsrc=dl_hpux.xs, dlext=sl, d_dlsymun=undef, ccdlflags='-Wl,-E -Wl,-B,deferred '
     cccdlflags='+z', lddlflags='-b -L/usr/local/lib -L/usr/ud/lib'


 Characteristics of this binary (from libperl):    Built under hpux  
 Compiled at May  7 1998 13:59:51   @INC:
     /opt/perl5/lib/PA-RISC2.0/5.00404
     /opt/perl5/lib
     /opt/perl5/lib/site_perl/PA-RISC2.0
     /opt/perl5/lib/site_perl
     .

...and here is config data from the new box (the one that is not working):

 > ./perl -V:usedl
 usedl='define';

 > ./perl -V
 Summary of my perl5 (revision 5 version 14 subversion 2) configuration:
       Platform:
     osname=hpux, osvers=11.31, archname=IA64.ARCHREV_0-LP64
     uname='hp-ux autocrft b.11.31 u ia64 1650208369 unlimited-user license '
     config_args=''
     hint=previous, useposix=true, d_sigaction=define
     useithreads=undef, usemultiplicity=undef
     useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
     use64bitint=define, use64bitall=define, uselongdouble=undef
     usemymalloc=n, bincompat5005=undef   Compiler:
     cc='cc', ccflags ='+DD64 -Ae -D_HPUX_SOURCE -Wl,+vnocompatwarnings -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
     optimize='+O2 +Onolimit',
     cppflags='-Aa -D__STDC_EXT__ -D_HPUX_SOURCE +DD64 -Ae -D_HPUX_SOURCE -Wl,+vnocompatwarnings -I/usr/local/include +DD64 -Ae -D_HPUX_SOURCE -Wl,+vnocompatwarn ings -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64'
     ccversion='B3910B', gccversion='', gccosandvers=''
     intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=87654321
     d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
     ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
     alignbytes=8, prototype=define   Linker and Libraries:
     ld='/usr/bin/ld', ldflags =' -L/usr/lib/hpux64'
     libpth=/usr/lib/hpux64
     libs=-L/usr/lib/hpux64 -lnsl -lnm -ldl -ldld -lm -lsec -lc
     perllibs=-lnsl -lnm -ldl -ldld -lm -lsec -lc
     libc=/usr/lib/hpux64/libc.so, so=so, useshrplib=false, libperl=libperl.a
     gnulibc_version=''
     Dynamic Linking:
     dlsrc=dl_hpux.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E -Wl,-B,deferred '
     cccdlflags='+DD64', lddlflags='-b +vnocompatwarnings'


 Characteristics of this binary (from libperl):
 Compile-time options: PERL_DONT_CREATE_GVSV PERL_MALLOC_WRAP
                         PERL_PRESERVE_IVUV USE_64_BIT_ALL USE_64_BIT_INT
                         USE_LARGE_FILES USE_PERLIO USE_PERL_ATOF   Built under hpux
 Compiled at Apr 13 2012 09:27:33
   @INC:
     /opt/iibase/perl/lib/site_perl/5.14.2/IA64.ARCHREV_0-LP64
     /opt/iibase/perl/lib/site_perl/5.14.2
     /opt/iibase/perl/lib/5.14.2/IA64.ARCHREV_0-LP64
     /opt/iibase/perl/lib/5.14.2
     .
j0k
  • 22,600
  • 28
  • 79
  • 90
Jonathan M
  • 17,145
  • 9
  • 58
  • 91
  • Look at the output of `perl -V`; it shows how it was compiled. Apparently, it was compiled without dynamic loading. Your best bet would be to rebuild it with dynamic loading. – Jonathan Leffler Apr 13 '12 at 16:25
  • @JonathanLeffler, is there a switch that specifically tells it dynamic or static? – Jonathan M Apr 13 '12 at 16:29
  • It does seem like the above procedure should create a `perl` that's identical to the original, but which has the extra library linked in. So if the original `perl` supported dynamic loading (and `perl -V:usedl` seemlingly indicates it does), then the new `perl` should also support dynamic loading. Sorry, I can't help you. – ikegami Apr 13 '12 at 18:06
  • Question: Is this is the only module for which you've use `make perl`? – ikegami Apr 13 '12 at 18:07
  • @ikegami, yes. On the old box and the new one. – Jonathan M Apr 13 '12 at 18:14
  • In the `perl -V` output is a section on 'Dynamic Linking', like this (no newlines in a comment, of course); this is from a Perl 5.12.1 on an ancient Linux: `Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E', cccdlflags='-fPIC', lddlflags='-shared -O2 -L/usr/local/lib -fstack-protector' `. It used (15 years ago) to be a problem that Perl was not always built with dynamic loading; then, adding an XS module to Perl involved building a whole new binary. It is much less often a problem these days. – Jonathan Leffler Apr 13 '12 at 18:16
  • @JonathanLeffler, I've posted the `-V` from both the old and new boxes to see if there's a major difference between the two. They both show to be using dynamic loading (if I'm reading it right), although I still get the message that dynamic loading is not available on the new box. – Jonathan M Apr 16 '12 at 14:11
  • Perl 5.4.4 (in the modern notation) vs 5.14.2; that's a huge step up. Also, PA-RISC to IA-64; another rather significant step. I note that the old (correctly) has `so=sl` and `dlext=sl`, whereas the new uses `so=so` and `dlext=so`, but that both use `dl_hpux.xs`. I found an IA64 machine running HP-UX 11.23 and its Perl 5.8.8 has 'so' and uses `dl_hpux.xs`, so that should be OK. Are you **sure** you must build the extended binary, rather than simply using a regular dynamically loaded module? Why? – Jonathan Leffler Apr 16 '12 at 15:04
  • @JonathanLeffler, The vendor says their libs must be linked in statically, and we've tried linking them dynamically with no success. Can't seem to identify why the old works and the new doesn't. Any other areas you suggest we investigate? – Jonathan M Apr 16 '12 at 15:19
  • Have you asked the library vendor about whether they've seen this problem and how they work around it? Have you asked the vendor about why they can't create dynamic libraries? Have you asked the vendor for the output from `perl -V` on one of their working Perl's? – Jonathan Leffler Apr 16 '12 at 15:40
  • @JonathanLeffler, we're getting their Professional Services group engaged. I'll ask them those questions. I'll post updates here (often SO solves these problems faster than the "experts". :) – Jonathan M Apr 16 '12 at 15:44
  • One peculiarity on HP-UX relates to thread-local storage (TLS) and shared libraries. I work on some (normally SUID root) software which dynamically loads a JVM, but we have to do that from a fixed location (`/usr/lib/`_software-package_`/`_jvm-version_`/libjvm.so`) so as deal with some TLS. I wonder if this could be a factor in your vendor's libraries needing to be statically loaded (which would be the other was for the software package to deal with the problem, but it presents different problems). I forget whether the SUID-root-ness of the software is a factor in the problem; it may be. – Jonathan Leffler Apr 23 '12 at 06:39

3 Answers3

1

I don't know if there is anything useful in this email that I collected and preserved as part of the background information for Perl's DBD::Informix module.

Date: Wed, 13 Aug 1997 13:02:04 -0500 (CDT)
From: "Kent S. Gordon" [email deleted]
Subject: Re: Easy way to force static Informix libraries with DBD:Informix

>> "kgor" == Kent S Gordon <kgor@inetspace.com> wrote:
> Is there a easy way to create a DBD:Informix that uses static Informix
> libraries, but dynamic system libraries for everything else.

I have succeeded in building a perl with DBD:Informix that uses dynamic
loading for everything except DBD:Informix and DBI.  I got a runtime error of
not being able to find the symbol of boot_DBI if DBI was also not
statically built into perl.  Here is a short discription of what I did.

1)  Built perl 5.004_2 normally.
2)  Installed perl.
3)  Built DBI statically (make static).
4)  Installed DBI (make install).  This is not just the install of the perl
    binary, since DBI.a is needed later.
5)  Changed DBD Makefile.pl to call esql -static and esql -static -libs
    instead of esql and esql -libs.
6)  Created DBD Makefile using perl Makefile.PL.
7)  Built DBD statically (make static and make perl, etc.)
8)  The make test_static failed, due to wanting to create a dynamic object
    (Informix.sl failed due to trying fixup a symbol)
9)  Installed with make -k install to get pass error creating Informix.sl,
    while still installing Informix.pm (could not find a special install
    for static perl.
10) Installed new perl executable.  It seems to work after some initial
    test.

Kent S. Gordon
Senior Software Engineer
iNetSpace Co.
[Phone and email deleted]

I noted at the time that Kent must be building on HP-UX because of the references to Informix.sl. I think there is nothing useful in here, but it is the only extra information I have on building statically linked versions of Perl. As you can see, it is close to 15 years old.

I wonder if Perl 5.14.x still fully supports and tests statically linked modules?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
1

Don't know if that would be of much help but you can take a look at App::Staticperl. I was able to build DBI and DBD::Informix with it in Solaris, maybe it will work in HP-UX as well.

Alex Tokarev
  • 4,821
  • 1
  • 20
  • 30
0

From perlxstut man page

Dynamic Loading versus Static Loading

It is commonly thought that if a system does not have the capability to dynamically load a library, you cannot build XSUBs. This is incorrect. You can build them, but you must link the XSUBs subroutines with the rest of Perl, creating a new executable. This situation is similar to Perl 4.

This tutorial can still be used on such a system. The XSUB build mechanism will check the system and build a dynamically-loadable library if possible, or else a static library and then, optionally, a new statically-linked executable with that static library linked in.

Should you wish to build a statically-linked executable on a system which can dynamically load libraries, you may, in all the following examples, where the command "make " with no arguments is executed, run the command "make perl " instead.

If you have generated such a statically-linked executable by choice, then instead of saying "make test ", you should say "make test_static ". On systems that cannot build dynamically-loadable libraries at all, simply saying "make test " is sufficient.

It says if you use the line command 'make perl' then you are telling it to build statically.