我喜欢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::Zilla
dzil
。
$ 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";