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



我喜欢local::lib的想法。至少,我发现它比默认的系统范围安装更可取,cpan/perl在大多数中都是这样。然而,我在安装XS的模块和更新Perls的分发升级方面遇到了困难。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的调用
  • 以及准备local::lib安装到的bin/目录的PATH

因此,基本上,在主目录中安装perl模块,并首先查找安装在主目录下的文件。

我的问题是,当你安装有XS的东西时会发生什么?在我的情况下,我有一个XS文件,

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

这是安装的,local::lib使用了早期版本的Perl。从那以后,我运行了一个Debiandist-upgrade,并获得了一个新版本的Perl(v5.36)。现在很多实用程序都会产生一个迟钝的错误,包括通过发行版本身安装的实用程序,比如我使用Debian的libdist-zilla-perl包安装的Dist::Zilladzil

$ 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升级将遗留旧版本中的所有XS。最好不要将local::lib安装到/home/ecarroll/perl5/lib/perl5/,而是安装到CCD28?注意添加的次要版本。那么至少dist升级不会破坏分发

Perl不维护版本之间的ABI兼容性。(例如,5.34.x->5.36.y。)安装新版本的Perl后,您将需要重新安装在arch目录中安装的模块(XS模块和其他一些模块)。删除(重命名)本地lib目录(/home/ecaroll/perl5)并从头开始可能是最简单、最安全的。

这就是为什么我避免使用发行版提供的perl模块以外的任何东西。包管理器确保您始终拥有模块的兼容版本。

如果这还不够好,我建议您安装自己的perl版本,而不是使用local::lib。像perlbrew这样的工具使这变得很容易。当你安装新的perl时,你仍然需要重新安装所有模块,但你会得到更干净的";找不到";如果您忘记了一条错误消息。

我很少使用local::lib,但在管理方面我也是一个极简主义者。你的层次越多,情况就越糟糕。正如您所看到的,您自己的答案(现已删除)提出了更高的复杂性来处理可能不适合您的情况的复杂性。

但是,local::lib有一种方法可以设置所有内容的位置。你试图对所有事情使用相同的位置,而不是根据你想要做的事情来更改位置。然而,即使local::lib允许你这样做,你也可能忘记切换。

我的解决方案更简单。我只是为我正在做的任何事情安装一个perl(或者重用一个合适的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,现在还有一些你认为可能解决问题的其他工具。如果你必须不断创建新的工具来处理你正在使用的工具,这是一个很大的危险信号。我宁愿把时间花在别的事情上。

我支持我的另一个答案——这太复杂了,你应该减少它。但是,让我们处理这个约束。您要使用local::lib

问题是,无论perl是如何编译的,您都试图在任何特定的CCD_37上强制使用相同的模块集。正如ikegami所解释的,你不能假设两个不同的perl,或者用不同perl编译的同一个库是兼容的。罪犯的版本无关紧要。两个不同的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"; 

相关内容

  • 没有找到相关文章

最新更新