linux local::lib应该如何处理XS和不同版本的Perl?

xuo3flqw  于 2022-12-11  发布在  Linux
关注(0)|答案(3)|浏览(239)

我喜欢local::lib的想法。至少,我发现它比cpan/perl在 * 大多数 * 情况下默认的全系统安装更好。但是,我在安装XS和发行版升级到较新的Perl的模块上遇到了困难。local::lib的说明要求将此行添加到您的.bashrc(或类似文件)

eval "$(perl -I$HOME/perl5/lib/perl5 -Mlocal::lib)"

执行任意shell代码,这很好。您可以通过运行

perl -I$HOME/perl5/lib/perl5 -Mlocal::lib

在我的例子中,它返回以下代码,

PATH="/home/ecarroll/perl5/bin${PATH:+:${PATH}}"; export PATH;
PERL5LIB="/home/ecarroll/perl5/lib/perl5${PERL5LIB:+:${PERL5LIB}}"; export PERL5LIB;
PERL_LOCAL_LIB_ROOT="/home/ecarroll/perl5${PERL_LOCAL_LIB_ROOT:+:${PERL_LOCAL_LIB_ROOT}}"; export PERL_LOCAL_LIB_ROOT;
PERL_MB_OPT="--install_base \"/home/ecarroll/perl5\""; export PERL_MB_OPT;
PERL_MM_OPT="INSTALL_BASE=/home/ecarroll/perl5"; export PERL_MM_OPT;

在上面的示例中,我们为两个最广泛使用的模块构建系统设置了默认选项,

  • MB代表Module::Build
  • MM代表ExtUtils::MakeMaker

我们告诉这些系统安装到/home/ecarroll/perl5

  • PERL5LIB,用于设置@INC。Perl中的@INC变量用于解析use调用。
  • 以及PATH,其预先规划local::lib安装到的bin/目录。

所以基本上,在您的home目录中安装perl模块,并首先查找安装在您的home目录中的文件。
我的问题是当你安装了带有XS的东西会发生什么?在我的例子中,我有一个XS文件,

/home/ecarroll/perl5/lib/perl5/x86_64-linux-gnu-thread-multi/auto/Class/Load/XS/XS.so

这是用local::lib安装的,使用的是Perl的早期版本。后来我运行了Debian dist-upgrade,得到了一个更新的Perl版本(v5.36)。现在很多实用程序都产生了一个关于这个的迟钝错误,包括那些通过发行版本身安装的,比如我的例子Dist::Zilladzil,我是用Debian's libdist-zilla-perl package安装的。

$ dzil
XS.c: loadable library and perl binaries are mismatched (got first handshake key 0xeb00080, needed 0xeb80080)

这都是这个模块XS的结果,

perl -MClass::Load::XS -e1
XS.c: loadable library and perl binaries are mismatched (got first handshake key 0xeb00080, needed 0xeb80080)

这看起来像是local::lib的常规用法:

  • 我是否按照预期的方式使用local::lib?我还应该做什么?
  • local::lib应该如何处理XS?
  • 有没有办法让local::lib支持Perl的多个版本?我的发行版读写它管理的XS到/usr/share/perl/$PERL_VERSION。这意味着dist-upgrade会把旧版本的所有XS都留在后面。如果local::lib不是安装到/home/ecarroll/perl5/lib/perl5/而是安装到/home/ecarroll/perl5/lib/perl5.30/会很好吗?注意增加的次要版本。那么至少dist-upgrade不会“不要破坏分配。
c3frrgcw

c3frrgcw1#

Perl在不同版本之间不保持ABI兼容性。(例如,5.34.x -〉5.36.y。)在安装了新版本的Perl之后,您需要重新安装那些安装在arch目录中的模块(XS模块和其他一些模块)。最简单和最安全的方法可能是删除(重命名)本地lib目录(/home/ecarroll/perl 5)并从头开始。
这就是为什么我避免使用除了distro提供的模块和distro提供的perl之外的任何东西。包管理器确保你总是有兼容的模块版本。
如果这还不够好,我建议安装您自己的perl版本,而不是使用local::lib。像perlbrew这样的工具使这变得容易。当您安装一个新的perl时,您仍然需要重新安装所有的模块,但是如果您忘记了一个模块,您会得到更清晰的错误消息“找不到”。

pbwdgjma

pbwdgjma2#

我很少使用local::lib,但在管理方面,我也是一个极简主义者。层次越多,情况就越糟糕。正如你所看到的,你自己的答案(现在被删除)提出了更高的复杂性来处理复杂性,这可能不适合你的情况。
但是,local::lib有一种方法可以设置所有东西的位置。你试图对所有东西使用相同的位置,而不是根据你想做的事情来改变位置。然而,即使local::lib允许你这样做,你也很可能忘记切换东西。
我的解决方案更简单,我只是install a perl for whatever I'm doing(或者重用一个合适的perl),我根本不改变默认位置,我从来不需要管理它,我只是调用我想要的perl:

$ ls -d /usr/local/perls/*
/usr/local/perls/perl-5.10.1    /usr/local/perls/perl-5.24.3    /usr/local/perls/perl-5.32.0
/usr/local/perls/perl-5.12.5    /usr/local/perls/perl-5.26.1    /usr/local/perls/perl-5.32.1
/usr/local/perls/perl-5.14.4    /usr/local/perls/perl-5.26.2    /usr/local/perls/perl-5.34.0
/usr/local/perls/perl-5.16.3    /usr/local/perls/perl-5.28.0    /usr/local/perls/perl-5.34.1
/usr/local/perls/perl-5.18.4    /usr/local/perls/perl-5.30.0    /usr/local/perls/perl-5.35.11
/usr/local/perls/perl-5.20.3    /usr/local/perls/perl-5.30.1    /usr/local/perls/perl-5.36.0
/usr/local/perls/perl-5.22.4    /usr/local/perls/perl-5.30.2    /usr/local/perls/perl-5.8.9

我有各种符号链接和稳定的路径调整,我使用工具名称和版本标记,我给它:

% cpan5.36.0 ...
% cpan5.32.1 ...

人们使用各种各样的工具,比如perlbrew,plenv,现在还有一些你认为可能解决这个问题的工具。如果你不得不不断地创建新的工具来处理你正在使用的工具,这是一个很大的危险信号。我宁愿把时间花在其他事情上。

piah890a

piah890a3#

我坚持我的另一个答案-这太复杂了,你应该减少它。但是,让我们处理这个约束。你想使用local::lib
问题是你试图在任何特定的perl上强制使用相同的模块集,不管它是如何编译的。正如ikegami所解释的,你不能假设两个不同的perls,或者用不同的perls编译的同一个库是兼容的。perls的版本并不重要。两个不同的perl5.36,或者任何版本,都可能彼此不兼容。
但是local::lib提供了设置适当值所需的信息,模块本身可以提供一些初始值:

$ perl -I$HOME/perl5/lib/perl5 -Mlocal::lib
Attempting to create directory /Users/brian/perl5
PATH="/Users/brian/perl5/bin${PATH:+:${PATH}}"; export PATH;
PERL5LIB="/Users/brian/perl5/lib/perl5${PERL5LIB:+:${PERL5LIB}}"; export PERL5LIB;
PERL_LOCAL_LIB_ROOT="/Users/brian/perl5${PERL_LOCAL_LIB_ROOT:+:${PERL_LOCAL_LIB_ROOT}}"; export PERL_LOCAL_LIB_ROOT;
PERL_MB_OPT="--install_base \"/Users/brian/perl5\""; export PERL_MB_OPT;
PERL_MM_OPT="INSTALL_BASE=/Users/brian/perl5"; export PERL_MM_OPT;

但是,您不需要在任何地方都使用这些值。您可以拥有任意多组这些变量。您可以为每个项目、每个perl或任何您想要的组织方式拥有不同的变量集。唯一的技巧是如何选择正确的变量集。
local::lib的概要表明它希望您为项目设置适当的值:

use FindBin;
use local::lib "$FindBin::Bin/../support";  # app-local support library

知道了这一点,你就可以通过在local::lib的路径中添加$^V来获得每个版本的库(仍然存在二进制不兼容的问题):

use FindBin;
use local::lib "/my/modules/$^V";

相关问题