我正试图通过Makefile.PL在linux主机上构建DBD::Pg;我的要求是,我必须能够动态地链接perl,但静态地链接libpq.so(因为它可能不适用于所有的盒子(。
有简单的方法吗?我尝试更改Makefile.PL的LIBS指令中的链接选项,但MakeMaker忽略了我的选项。
IMO您错误地指定了您的要求。
您不需要静态链接到libpq
,因为它可能在所有系统上都不可用。
您通常应该做的是动态链接到libq
,并在包装脚本中设置LD_LIBRARY_PATH
或使用rpath
链接,以便可以找到libpq
。
请注意,无论是静态链接还是动态链接,如果其他模块将libpq
加载到同一Perl中,您要么会将两个不兼容的libpq
链接到同一可执行文件中(boom(,要么会将其中一个模块使用与其编译对象不同的libpq
(也是boom(。如果您使用rpath链接,ld.so
对链接作用域的感知可能会让您逃脱惩罚,但设置LD_LIBRARY_PATH
几乎肯定会引起问题。
您可能需要研究将rpath
与$ORIGIN
一起使用。
不幸的是,尝试对libpq
进行静态链接不太可能解决您的问题。
libpq
本身可能依赖于libc
(glibc
(。如果您静态地链接它,但动态地链接其他模块,这意味着您将拥有libc
的两个副本:一个在libpq
中,另一个由Perl本身引用并动态加载。这是非常危险的情况,尤其是当某个过程使用malloc
分配内存并将指针传递回调用方时。如果您的内存是由malloc从libc
的一个副本分配的,但free
被另一个副本占用,那么您的程序(和Perl(肯定会崩溃。
换言之,如果您想进行静态编译,则必须执行所有操作-所有操作都必须100%静态编译,因此应用程序只能使用libc
的一个副本。反之亦然——如果你是动态的,那么一切都应该是动态的——就像只使用libc
的一个副本一样。只有当您的库没有使用libc
中的任何内容(甚至没有sprintf
(时,这些规则才适用。
即使您成功地进行了静态libpq
编译,并且它会工作(不太可能(,如果没有安装DBI
呢?我已经看到了足够多默认情况下不存在DBI的Linux盒子。那么你也静态编译DBI吗?如果Perl
不存在(在Linux上不太可能(,或者它很旧,该怎么办?
正确的解决方案是使用本机操作系统包管理器安装:
sudo apt-get install libdbd-pg-perl # Ubuntu/Debian
sudo yum install perl-DBD-Pg # Redhat/Fedora
如果您在有问题的主机上没有root,也许您应该考虑使用perlbrew
——在主目录中安装您自己的Perl。这样,您就可以编译自己的libpq
副本,并将其与perlbrew
提供的Perl动态链接。