使用Scalar::Util运行perl脚本失败,并显示“尝试重新加载Scalar/Util.pm中止”,

wyyhbhjk  于 2022-11-15  发布在  Perl
关注(0)|答案(1)|浏览(203)

我最近换了一台Mac Book Pro M1(来自Ubuntu),并安装了自制的Perl。
我已经安装了一些我常用的perl软件包,没有任何问题。不幸的是,在运行时,任何依赖于(或使用依赖于)Scalar::Util或List::Util的perl程序都会失败,错误如下:

Attempt to reload Scalar/Util.pm aborted.
Compilation failed in require at /opt/homebrew/Cellar/perl/5.34.0/lib/perl5/site_perl/5.34.0/YAML.pm line 21.
BEGIN failed--compilation aborted at /opt/homebrew/Cellar/perl/5.34.0/lib/perl5/site_perl/5.34.0/YAML.pm line 21.
...

Can't load '/opt/homebrew/Cellar/perl/5.34.0/lib/perl5/site_perl/5.34.0/darwin-thread-multi-2level/auto/List/Util/Util.bundle' for module List::Util: dlopen(/opt/homebrew/Cellar/perl/5.34.0/lib/perl5/site_perl/5.34.0/darwin-thread-multi-2level/auto/List/Util/Util.bundle, 0x0001): symbol not found in flat namespace (_Perl_croak_memory_wrap) at /System/Library/Perl/5.30/XSLoader.pm line 96.
 at /opt/homebrew/Cellar/perl/5.34.0/lib/perl5/site_perl/5.34.0/darwin-thread-multi-2level/List/Util.pm line 24.
Compilation failed in require at /opt/homebrew/Cellar/perl/5.34.0/lib/perl5/site_perl/5.34.0/darwin-thread-multi-2level/Scalar/Util.pm line 23.

我也尝试过安装perlbrew作为替代方案,但没有成功。我也检查了所有内容都正确地出现在PERL5LIB路径中。
使用List::Util我已经设法从CPAN安装了一个更新的版本,但仍然得到同样的错误。(内置的Scalar::Util是最新版本)
任何关于如何让他们工作的建议,我担心这是一个M1的问题,但我不确定这可能是一个xcode的问题,我猜。
您可以通过以下方式复制此功能:

$ cpanm VCSL::Which
$ vcsvimdiff -v
Can't load '/opt/homebrew/Cellar/perl/5.34.0/lib/perl5/site_perl/5.34.0/darwin-thread-multi-2level/auto/List/Util/Util.bundle' for module List::Util: dlopen(/opt/homebrew/Cellar/perl/5.34.0/lib/perl5/site_perl/5.34.0/darwin-thread-multi-2level/auto/List/Util/Util.bundle, 0x0001): symbol not found in flat namespace (_Perl_croak_memory_wrap) at /System/Library/Perl/5.30/XSLoader.pm line 96.
 at /opt/homebrew/Cellar/perl/5.34.0/lib/perl5/site_perl/5.34.0/darwin-thread-multi-2level/List/Util.pm line 24.
Compilation failed in require at /opt/homebrew/Cellar/perl/5.34.0/bin/vcsvimdiff line 12.
BEGIN failed--compilation aborted at /opt/homebrew/Cellar/perl/5.34.0/bin/vcsvimdiff line 12.

不幸运行

perl -MScalar::Util -e 1
or
perl -MList::Util -e 1

两个都运行成功。我看了看我的PERL5LIB路径,只看到了那里的自制perl路径。

$ perl -E 'say join "\n", split /:/, $ENV{PERL5LIB}'

/opt/homebrew/Cellar/perl/5.34.0/lib/perl5
/opt/homebrew/Cellar/perl/5.34.0/lib/perl5/site_perl/5.34.0
/opt/homebrew/Cellar/perl/5.34.0/lib/perl5
/opt/homebrew/Cellar/perl/5.34.0/lib/perl5/site_perl/5.34.0
/opt/homebrew/Cellar/perl/5.34.0/lib/perl5
/opt/homebrew/Cellar/perl/5.34.0/lib/perl5/site_perl/5.34.0

所有这些看起来都很好,没有系统perl引用

zmeyuzjn

zmeyuzjn1#

摘要:

  • 检查您是否遗漏了某些内容
  • 检查perl -V以查看它是哪个perl以及它的默认模块搜索路径
  • 检查环境变量(如PERL 5LIB)是否存在冲突值
  • 在shebang行中查找正在运行的程序

东西都带齐了吗?
正如Håkon所指出的,看起来有两个perl安装互相干扰。但是,也正如池上所说的“从未见过”错误信息。我也没有,但是StackOverflow has seen it
[perldiag]中的条目表示程序尝试加载模块,第一次失败,然后再次尝试:

Attempt to reload %s aborted.
        (F) You tried to load a file with "use" or "require" that failed to
        compile once already. Perl will not try to compile this file again
        unless you delete its entry from %INC. See "require" in perlfunc and
        "%INC" in perlvar.

我不知道是什么让它在第一次时不会失败,但是您应该使用一些简单的方法来检查是否可以加载该模块:

$ perl -MScalar::Util -e 1

但是,实际上比这更棘手。也许perl可以加载它,但其他一些perl不能。而且,也许您安装了多个Scalar::Util,但特定的perl、环境和程序设置合谋选择了错误的一个。

环境可以告诉perl在哪里查找

但是,也许这些都不起作用。
首先,确定要使用哪个perl,并检查其设置:

$ perl -V

在输出的最后,您应该看到有趣的环境设置和默认的模块搜索路径。

%ENV:
  @INC:
    /usr/local/perls/perl-5.36.0/lib/site_perl/5.36.0/darwin-2level
    /usr/local/perls/perl-5.36.0/lib/site_perl/5.36.0
    /usr/local/perls/perl-5.36.0/lib/5.36.0/darwin-2level
    /usr/local/perls/perl-5.36.0/lib/5.36.0

但是,我可以把环境弄得更脏,我将设置一个PERL5LIB值,它把目录放在默认的模块搜索路径前面:

$ export PERL5LIB=/usr/local/perls/perl-5.10.1/lib/5.10.1/darwin-2level:/usr/local/perls/perl-5.10.1/lib/5.10.1:/usr/local/perls/perl-5.10.1/lib/site_perl/5.10.1/darwin-2level:/usr/local/perls/perl-5.10.1/lib/site_perl/5.10.1

再次检查perl -V,会发生以下有趣的事情:

Perl lib version (5.10.1) doesn't match executable version (v5.36.0) at /usr/local/perls/perl-5.10.1/lib/5.10.1/darwin-2level/Config.pm line 50.
Compilation failed in require.
BEGIN failed--compilation aborted.

如果我尝试从命令行使用-M加载Scalar::Util,这是我所期望的,如果您混淆了perls:

$ perl -MScalar::Util -e 1
Can't load '/usr/local/perls/perl-5.10.1/lib/5.10.1/darwin-2level/auto/List/Util/Util.bundle' for module List::Util: dlopen(/usr/local/perls/perl-5.10.1/lib/5.10.1/darwin-2level/auto/List/Util/Util.bundle, 0x0001): symbol not found in flat namespace '_PL_sv_no' at /usr/local/perls/perl-5.10.1/lib/5.10.1/darwin-2level/XSLoader.pm line 73.
 at /usr/local/perls/perl-5.10.1/lib/5.10.1/darwin-2level/List/Util.pm line 23
Compilation failed in require at /usr/local/perls/perl-5.10.1/lib/5.10.1/darwin-2level/Scalar/Util.pm line 23.
Compilation failed in require.
BEGIN failed--compilation aborted.

程序可能未正确调整@INC

我不认为这是cpanm的问题,因为现在全世界都会抱怨。但是,如果某个程序在@INC上做了一些奇怪的事情,它可能添加了错误的东西。
我认为可能的情况是他们使用一组供应商模块目录,其中一些模块针对特定的perl。当您使用不同的perl时,会出现二进制不匹配的情况。

程序选择其解释程序

但是,还有另外一个部分。你正在运行一些程序,这些程序选择了perl。如果你看它们的第一行,它们要么有一个perl的绝对路径,如下所示:

#!/usr/bin/perl

或者,他们会耍花招,在您的PATH中找到第一个perl:

#!/usr/bin/env perl

我不喜欢第二个,因为我从来不确定它会先找到哪个perl。(或者为您将其添加到PATH中),然后表现得像真实的的perl一样,但沿着关闭污染检查。但是当你让程序猜测谁来处理它时,奇怪的事情就会发生。
例如,我想我还没有安装cpanm v5.36.0:

$ head -1 `which cpanm`
#!/usr/local/perls/perl-5.34.1/bin/perl

当我只运行cpanm时,它将使用v5.34.1和我为此所做的任何设置。
我可以直接告诉它要使用哪个perl,但是我需要告诉perl在哪里可以找到这个程序:

$ perl5.36.0 `which cpanm` ...

同样,我有一些程序的旧版本,我用我打算使用的版本来处理这些程序(我做了很多事情,这些事情都是针对很多很多perls运行的):

$ head -1 `which cpan5.10.1`
#!/usr/local/perls/perl-5.10.1/bin/perl

$ head -1 `which cpan5.12.5`
#!/usr/local/perls/perl-5.12.5/bin/perl

当你安装程序时,比如cpanm,安装程序会调整安装它的perl的shebang行。简单地运行cpanm并不意味着你正在安装到你认为你是的perl

相关问题