如何获取软件包所需的模块列表?

时间:2018-09-26 19:10:24

标签: perl

我正在为Mo * se类系统编写扩展,我需要使用“ use”语句从包内部获取包所需的所有模块的列表。 我试图检查%INC数据结构,但是在编译时获得了所有已加载模块的列表,而我无法过滤掉我的包所加载的模块。 我想我必须处理Perl调试器,但是任何建议都会很感激:-)

例如:

package MyApp 0.001 ;
use Module1 ;
use Module2 ;
...
sub list_requested_modules {
    ...HOW TO DO IT ???
}

2 个答案:

答案 0 :(得分:3)

您无法区分当前文件中已加载的模块还是已加载的模块。考虑您是否具有“使用Module1;”。但是Module1已被加载,因此所有操作都已从已加载的模块导入到当前包中。然后您会认为该模块从何处加载?

根据要尝试的内容,您可以执行以下两项操作:您可以解析文件以猜测所需的模块(尽管不能保证它们将从此处加载,但可以在我加载时加载它们)前面提到的)。 Perl::PrereqScanner::Lite是一个很好的工具。您可以使用__FILE__文字获取当前文件的名称。

use Perl::PrereqScanner::Lite;
my @required = Perl::PrereqScanner::Lite->new->scan_file(__FILE__)->required_modules;

另一个选择是跟踪自己加载了哪些模块。在文件的开头放置以下内容:

my %original_inc;
BEGIN { %original_inc = %INC }

然后立即查找在编译时加载的任何模块(包括use语句),或者在以后的子例程中,可以比较%INC的更改方式:

my @newly_loaded = grep { !exists $original_inc{$_} } keys %INC;

除了前面提到的警告,即以前可能已经需要模块,因此已经在%INC中提供了该模块,您加载的模块可能会依次加载其他模块,因此差异可能与{{1 }}语句在文件中。

编辑:就我个人而言,我将首先避免使用此类逻辑,从而避免了这两种方法。而不是使用use加载模块,而是编写一个子例程,该子例程使用Module::Runtime加载它们,并以某种方式跟踪使用它加载的内容,并在BEGIN块中为每个模块调用该例程。但是请注意,这会破坏自动的prereq扫描,例如我上面提到的PrereqScanner模块。

答案 1 :(得分:1)

另一个选择,如果您对知道当前文件将要加载/已加载的模块感兴趣,则为PPI

use warnings;
use strict;

use Data::Dumper;
use PPI;
require Mock::Sub;

my $ppi_doc  = PPI::Document->new(__FILE__);
my $ppi_deps = $ppi_doc->find('PPI::Statement::Include');

for (@$ppi_deps){
    print $_->module . "\n";
}

输出:

warnings
strict
Data::Dumper
PPI
Mock::Sub