扩展Perl会破坏动态加载

10

我正在尝试将XS编译到perl中 [ed(ikegami): 这意味着他正在使用::MakeMaker的make perl来创建一个具有静态链接C供应商库的perl] 但是当我这样做时,新版本的perl不支持动态加载模块。每次我尝试运行带有use Socket(或任何其他模块)的perl代码时,我都会遇到以下问题:

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

是否有编译器/链接器开关设置不正确的问题?所有这些都是在1998年和2004年在另一台机器上编译的(PA-RISC上的旧版hpux),但我们正在转移到新的机器(hpux11 itanium),我遇到了障碍。

以下是我的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',
);

这是我的.xs文件,名称为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)));
    }

当我运行perl Makefile.PL时,一切看起来都很好:
> perl Makefile.PL
Checking if your kit is complete...
Looks good
Writing Makefile for Udtutil
Writing MYMETA.yml

当我运行makemake perl时,一切都很顺利,它创建了一个新的本地perl二进制文件。
然而,当我执行./perl mytest.pl时,如果mytest.pl *使用*任何模块,我会得到以下错误:
Can't load module Socket, dynamic loading not available in this perl.

任何建议如何编译这个新的perl并保持动态加载正常运行?
附加信息: 以下是旧机器的配置数据(可以正常工作):
 > 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
     .

这里是来自新盒子(不工作的那个)的配置数据:

 > ./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
     .

看一下 perl -V 的输出;它会显示它是如何编译的。显然,它是没有动态加载编译的。你最好重新编译它以启用动态加载。 - Jonathan Leffler
@ikegami,是的。在旧盒子和新盒子上都是这样。 - Jonathan M
perl -V 的输出中有一个关于“动态链接”的部分,格式如下(当然,在注释中没有换行); 这是来自旧版Linux上的Perl 5.12.1:`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'。15年前,Perl不总是使用动态加载构建,这曾经是个问题;然后,在Perl中添加一个XS模块就涉及到构建一个全新的二进制文件。但这些年来,这种情况发生得更少了。 - Jonathan Leffler
@JonathanLeffler,供应商表示他们的库必须以静态方式链接,我们尝试了动态链接但没有成功。似乎无法确定为什么旧版本可以工作而新版本不行。您有其他建议我们可以调查的地方吗? - Jonathan M
你是否向库供应商询问过他们是否遇到过这个问题以及如何解决它?你是否询问过供应商为什么不能创建动态库?你是否向供应商要求获取他们工作的Perl之一的perl -V输出? - Jonathan Leffler
显示剩余7条评论
3个回答

1

不知道这是否有用,但你可以看看 App::Staticperl。我能够在 Solaris 上使用它构建 DBI 和 DBD::Informix,也许在 HP-UX 上也能行。


1

我不知道这封邮件中是否有任何有用的信息,它是我作为Perl的DBD::Informix模块背景信息而收集和保存的一部分。

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]

我当时注意到肯特一定是在使用HP-UX,因为有关Informix.sl的引用。我认为这里没有什么有用的信息,但这是我拥有的有关构建静态链接版本Perl的唯一额外信息。正如您所看到的,它已经接近15年了。

我想知道Perl 5.14.x是否仍然完全支持和测试静态链接模块?


0

来自perlxstut手册页面

动态加载与静态加载

通常认为,如果一个系统没有动态加载库的能力,就无法构建XSUBs。这是不正确的。您可以构建它们,但必须将XSUBs子例程与Perl的其余部分链接起来,创建一个新的可执行文件。这种情况类似于Perl 4。

在这样的系统上仍然可以使用本教程。XSUB构建机制将检查系统并构建一个可动态加载的库,如果可能的话,或者构建一个静态库,然后选择性地使用该静态库链接一个新的静态链接可执行文件。

如果您希望在可以动态加载库的系统上构建静态链接可执行文件,则可以在所有以下示例中执行“make”命令而不带参数,改为执行“make perl”命令。

如果您已经通过选择生成了这样的静态链接可执行文件,则应该说“make test_static”而不是“make test”。在完全无法构建可动态加载库的系统上,只需说“make test”即可。

它说如果您使用行命令'make perl',那么您就是在告诉它进行静态构建。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接