无法从 CPAN 安装 Perl 模块

Can't install a Perl module from CPAN

尝试 运行 Linux 上的 Perl 脚本时出现错误:“找不到 Devel/GlobalDestruction.pm”

所以,我 运行 CPAN shell 并尝试安装它:

$ perl -MCPAN -e shell
cpan> install Devel::GlobalDestruction

但是,不幸的是,出现了一个错误:

...
Looks good
Warning: prerequisite Devel::GlobalDestruction::XS 0 not found.
Warning: prerequisite Sub::Exporter::Progressive 0.001011 not found.
Only one of PREFIX or INSTALL_BASE can be given.  Not both.
No 'Makefile' created  HAARG/Devel-GlobalDestruction-0.13.tar.gz
  /usr/bin/perl Makefile.PL PREFIX=/home/onlinetv/perl/usr -- NOT OK
Failed during this command:
 HAARG/Devel-GlobalDestruction-0.13.tar.gz    : writemakefile NO -- No 'Makefile' created

可能这里有问题:“只能给出 PREFIX 或 INSTALL_BASE 之一。不能同时给出。”

但我不知道如何解决。

更新

>o conf 输出如下:

make_arg           [PREFIX=/home/onlinetv/perl/usr]
make_install_arg   []
make_install_make_command undef
makepl_arg         [PREFIX=/home/onlinetv/perl/usr]
mbuild_install_build_command [./Build]
mbuildpl_arg       [PREFIX=/home/onlinetv/perl/usr]

我只打印了与 PREFIX 相关的行

-bash-3.2$ set | grep ^PERL
PERL5LIB=/home/onlinetv/perl5/lib/perl5
PERL_LOCAL_LIB_ROOT=/home/onlinetv/perl5
PERL_MB_OPT='--install_base "/home/onlinetv/perl5"'
PERL_MM_OPT=INSTALL_BASE=/home/onlinetv/perl5

当您有很多时间并考虑 Whosebug 时,cpan 是一个不错的工具。请安装 App::cpanminus 并改用 cpanm。

curl -L https://cpanmin.us | perl - --sudo App::cpanminus

要解决此错误:

尝试 运行 Linux 上的 Perl 脚本,我得到一个错误:“找不到 Devel/GlobalDestruction.pm”

cpanm

我用宫川达彦的cpanm

按照该文档中的个人安装指南,下一节将把 cpanm 安装到 ~/bin,它需要位于你的 PATH.

cd ~/bin
curl -L https://cpanmin.us/ -o cpanm
chmod +x cpanm
which cpanm

现在使用 cpanm 将缺少的库安装在一个名为 local 的目录中,该目录位于包含原始脚本的给定目录中,例如 目录:

cd <dir>
cpanm -L local Devel::GlobalDestruction

要包含安装在该目录中的包,

  • 使用FindBin定位当前本地目录,

  • 使用 lib 找到您最近安装的文件。

这是添加到原始脚本的代码,位于 dir

use FindBin qw( $Bin );
use lib “$Bin/local/lib/perl5”;

cpanm 代码递归安装所有依赖项。在我的会话中,我得到了这两个:

cpanm -L local Devel::GlobalDestruction
--> Working on Devel::GlobalDestruction
Fetching http://www.cpan.org/authors/id/H/HA/HAARG/Devel-GlobalDestruction-0.13.tar.gz ... OK
Configuring Devel-GlobalDestruction-0.13 ... OK
==> Found dependencies: Sub::Exporter::Progressive
--> Working on Sub::Exporter::Progressive
Fetching http://www.cpan.org/authors/id/F/FR/FREW/Sub-Exporter-Progressive-0.001011.tar.gz ... OK
Configuring Sub-Exporter-Progressive-0.001011 ... OK
Building and testing Sub-Exporter-Progressive-0.001011 ... OK
Successfully installed Sub-Exporter-Progressive-0.001011
Building and testing Devel-GlobalDestruction-0.13 ... OK
Successfully installed Devel-GlobalDestruction-0.13
2 distributions installed 

作为上述的一个小变体

cpanm 参数从上 L [-L] 更改为下 l [-l] 以查看它们是否完整或不在包依赖项集中是否存在差异。

在两次尝试之间删除 local 目录以确保安装的软件包最少。


一个测试

作为上述使用的示例,这里是对 03_minusc.t 测试用例的修改,它在我将上述库下载到名为 的目录中找到新库本地

本link同原考:

http://cpansearch.perl.org/src/HAARG/Devel-GlobalDestruction-0.13/t/03_minusc.t

这里是对代码的修改:

use FindBin qw( $Bin );
use lib "$Bin/local/lib/perl5";
use Devel::GlobalDestruction;

这是输出:

1..3
ok - Test properly running under minus-c
ok - BEGIN is not GD with -c
./test.pl syntax OK
ok - Final cleanup object destruction properly in GD

看了思南的post,我觉得我下面用的perl,/opt/local/bin/perl,应该改成他推荐的/home/onlinetv/perl/bin/perl

修改后的测试代码如下:

#!/opt/local/bin/perl

BEGIN {
  if ($ENV{DEVEL_GLOBALDESTRUCTION_PP_TEST}) {
    unshift @INC, sub {
      die 'no XS' if $_[1] eq 'Devel/GlobalDestruction/XS.pm';
    };
  }
}

{
  package Test::Scope::Guard;
  sub new { my ($class, $code) = @_; bless [$code], $class; }
  sub DESTROY { my $self = shift; $self->[0]->() }
}

sub ok ($$) {
  print "not " if !$_[0];
  print "ok";
  print " - $_[1]" if defined $_[1];
  print "\n";
  !!$_[0]
}

BEGIN {
  require B;
  B::minus_c();

  print "1..3\n";
  ok( $^C, "Test properly running under minus-c" );
}

use FindBin qw( $Bin );
use lib "$Bin/local/lib/perl5";
use Devel::GlobalDestruction;

BEGIN {
    ok !in_global_destruction(), "BEGIN is not GD with -c";
}

our $foo;
BEGIN {
  $foo = Test::Scope::Guard->new( sub {
    ok( in_global_destruction(), "Final cleanup object destruction properly in GD" ) or do {
      require POSIX;
      POSIX::_exit(1);
    };
  });
}

cpan 配置为向 Makefile.PL 提供一个设置,而 Makefile.PL 正在从环境中获取一个冲突设置。

您似乎使用了 local::lib,它使用了 INSTALL_BASE 范式。因此,只需告诉 cpan 停止指定 PREFIX。来自 cpan shell,

o conf makepl_arg ''
o conf mbuildpl_arg ''
o conf commit

同时修正make_arg的无意义值。

o conf make_arg ''
o conf commit