如何查看特定 Perl 模块需要的所有模块?

How can I see all modules that a specific Perl module requires?

假设我得到了一个像 Data::Validate::IP 这样的模块,我想查看它需要的所有模块 (uses),我该怎么做呢?我正在寻找审核模块的依赖项。

进口追踪

您可以使用 Devel::TraceUse 查看相关模块使用的所有模块,

perl -d:TraceUse -MData::Validate::IP -e1

请注意,它只测试编译时包含的内容,要查看它可能使用 require 等引入的所有代码,请实际尝试 运行 代码,

perl -d:TraceUse -MData::Validate::IP -e'Data::Validate::IP::is_ipv4("1.2.3.4")'

示例输出

Modules used from -e:
   1.  Data::Validate::IP 0.27, -e line 0 [main]
   2.    strict 1.11, Data/Validate/IP.pm line 3
   3.    warnings 1.47, Data/Validate/IP.pm line 4
   4.    NetAddr::IP  4.079, Data/Validate/IP.pm line 10
   5.      Carp 1.50, NetAddr/IP.pm line 7
   6.        overloading 0.02, Carp.pm line 170
   7.        Exporter 5.74, Carp.pm line 224
  18.          Exporter::Heavy 5.74, Exporter.pm line 16
   8.      NetAddr::IP::Lite 1.57, NetAddr/IP.pm line 8
   9.        NetAddr::IP::InetBase 0.08, NetAddr/IP/Lite.pm line 17
  10.          vars 1.05, NetAddr/IP/InetBase.pm line 8
  11.            warnings::register 1.04, vars.pm line 7
  12.          AutoLoader 5.74, NetAddr/IP/InetBase.pm line 9
  15.            auto/NetAddr/IP/InetBase/AF_INET6.al, AutoLoader.pm line 34 (FAILED)
  13.          Socket 2.029, NetAddr/IP/InetBase.pm line 77
  14.            XSLoader 0.30, Socket.pm line 701
  16.          Socket6 0.29, NetAddr/IP/InetBase.pm line 85
  17.            base 2.27, Socket6.pm line 215
  19.        NetAddr::IP::Util 1.53, NetAddr/IP/Lite.pm line 31
  20.          NetAddr::IP::Util_IS 1, NetAddr/IP/Util.pm line 10
  21.        overload 1.31, NetAddr/IP/Lite.pm line 280
  22.    Scalar::Util 1.55, Data/Validate/IP.pm line 11
  23.      List::Util 1.55, Scalar/Util.pm line 23
Modules used, but not reported:
  /usr/local/cpanel/3rdparty/perl/532/lib/perl5/cpanel_lib/x86_64-linux-64int/auto/NetAddr/IP/InetBase/autosplit.ix
  /usr/local/cpanel/3rdparty/perl/532/lib/perl5/cpanel_lib/x86_64-linux-64int/auto/NetAddr/IP/InetBase/inet_any2n.al
  /usr/local/cpanel/3rdparty/perl/532/lib/perl5/cpanel_lib/x86_64-linux-64int/auto/NetAddr/IP/InetBase/ipv6_aton.al
  /usr/local/cpanel/3rdparty/perl/532/lib/perl5/cpanel_lib/x86_64-linux-64int/auto/NetAddr/IP/Util/autosplit.ix
  /usr/local/cpanel/3rdparty/perl/532/lib/perl5/cpanel_lib/x86_64-linux-64int/auto/NetAddr/IP/autosplit.ix

这些服务可以向您显示已声明的依赖项:

  • MetaCPAN 显示模块的依赖列表。它还显示“反向依赖关系”,因此您可以看到什么使用了模块。

  • CPAN Dependency Graphs 将以图像形式显示依赖信息。

  • 我经常查看 %INC 的结果,它显示了加载的内容(但不显示由谁加载)。这在尝试获得 100% 的测试覆盖率以了解您获得了大部分内容时非常方便。但是,除非代码使用它们,否则这仍然不会选择可选或动态模块。

CPAN::Dependencies 中的 cpandeps 工具也很方便:

$ cpandeps Business::ISBN
Business::ISBN (dist: B/BD/BDFOY/Business-ISBN-3.006.tar.gz)
  Business::ISBN::Data (dist: B/BD/BDFOY/Business-ISBN-Data-20210112.006.tar.gz)
    Carp (dist: X/XS/XSAWYERX/Carp-1.50.tar.gz)
      Exporter (dist: T/TO/TODDR/Exporter-5.74.tar.gz)
      IPC::Open3 (dist: S/SH/SHAY/perl-5.32.1.tar.gz)
      Test::More (dist: E/EX/EXODIST/Test-Simple-1.302183.tar.gz)
        File::Temp (dist: E/ET/ETHER/File-Temp-0.2311.tar.gz)
          File::Path (dist: J/JK/JKEENAN/File-Path-2.18.tar.gz)
            File::Spec::Functions (dist: X/XS/XSAWYERX/PathTools-3.75.tar.gz)
              Scalar::Util (dist: P/PE/PEVANS/Scalar-List-Utils-1.55.tar.gz)
          parent (dist: C/CO/CORION/parent-0.238.tar.gz)
        Storable (dist: X/XS/XSAWYERX/Storable-3.15.tar.gz)
          XSLoader (dist: S/SA/SAPER/XSLoader-0.24.tar.gz)
    ExtUtils::MakeMaker (dist: B/BI/BINGOS/ExtUtils-MakeMaker-7.60.tar.gz)
      Encode (dist: D/DA/DANKOGAI/Encode-3.08.tar.gz)
      Pod::Man (dist: R/RR/RRA/podlators-4.14.tar.gz)
        Pod::Simple (dist: K/KH/KHW/Pod-Simple-3.42.tar.gz)
          Pod::Escapes (dist: N/NE/NEILB/Pod-Escapes-1.07.tar.gz)
          Test (dist: J/JE/JESSE/Test-1.26.tar.gz)
          Text::Wrap (dist: M/MU/MUIR/modules/Text-Tabs+Wrap-2013.0523.tar.gz)
          if (dist: X/XS/XSAWYERX/if-0.0608.tar.gz)

还有各种静态分析工具:

  • 我写了 Module::Extract::Use 来提取在特定情况下出现的名称空间(userequirebaseparent).字面裸词需要在那里。

  • MetaCPAN::Client and Module::CoreList可以通过多种方式配置信息。在这里,我得到了所有不是 perl 本身的运行时依赖项,也不是核心模块。不过,您可以过滤其他内容:

use v5.10;

use MetaCPAN::Client;
use Module::CoreList;

my $metacpan = MetaCPAN::Client->new;

my @queue = map { [ 0, $_ ] } @ARGV;

while( my $tuple = shift @queue ) {
    state %Seen;

    my $release = eval { $metacpan->release( $tuple->[1] =~ s/::/-/gr ) };
    next unless $release;
    say "\t" x $tuple->[0], $release->distribution, 
        defined $tuple->[2] ? " $tuple->[2]" : '';
    push @queue,
        map  { [ $tuple->[0] + 1, $_->{module}, $_->{version} ] }
        grep { $_->{module} ne 'perl' }
        grep { $_->{phase}  eq 'runtime' }
        grep { ! Module::CoreList::is_core( $_->{module}, undef, $^V ) }
        grep { ! $Seen{ $_->{module} }++ }
        $release->dependency->@*;
    }