有没有人建议找到可能在定制开发项目中出现的所有CPAN依赖关系的好方法.往往是这样的情况,您的本地开发环境很少与您的实时开发环境匹配,并且当您构建越来越多的项目时,您倾向于构建已安装模块的本地库.这些导致您不一定注意到您的最新项目对非核心模块有要求.由于通常需要将整个项目打包以部署到另一个组(在我们的案例中是我们的运营团队),因此了解应该包含哪些模块非常重要.
有没有人对这个问题有任何见解.
谢谢
彼得
我自己也遇到过这个问题. Devel :: Modlist(如本答案所示)采用动态方法.它报告在特定的脚本运行期间实际加载的模块.这会捕获以任何方式加载的模块,但它可能无法捕获条件要求.也就是说,如果你有这样的代码:
if ($some_condition) { require Some::Module }
并且$some_condition
恰好是假的,Devel::Modlist
不会Some::Module
列为要求.
我决定使用Module :: ExtractUse.它进行静态分析,这意味着它将始终捕获Some::Module
上面的示例.另一方面,它对代码无能为力:
my $module = "Other::Module"; eval "use $module;";
当然,您可以使用这两种方法然后合并两个列表.
无论如何,这是我提出的解决方案:
#! /usr/bin/perl #--------------------------------------------------------------------- # Copyright 2008 Christopher J. Madsen# # This program is free software; you can redistribute it and/or modify # it under the same terms as Perl itself. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either the # GNU General Public License or the Artistic License for more details. # # Recursively collect dependencies of Perl scripts #--------------------------------------------------------------------- use strict; use warnings; use File::Spec (); use Module::CoreList (); use Module::ExtractUse (); my %need; my $core = $Module::CoreList::version{'5.008'}; # These modules have lots of dependencies. I don't need to see them now. my %noRecurse = map { $_ => 1 } qw( Log::Log4perl XML::Twig ); foreach my $file (@ARGV) { findDeps($file); } foreach my $module (sort keys %need) { print " $module\n"; } #--------------------------------------------------------------------- sub findDeps { my ($file) = @_; my $p = Module::ExtractUse->new; $p->extract_use($file); foreach my $module ($p->array) { next if exists $core->{$module}; next if $module =~ /^5[._\d]+/; # Ignore "use MIN-PERL-VERSION" next if $module =~ /\$/; # Run-time specified module if (++$need{$module} == 1 and not $noRecurse{$module}) { my $path = findModule($module); if ($path) { findDeps($path) } else { warn "WARNING: Can't find $module\n" } } # end if first use of $module } # end foreach $module used } # end findDeps #--------------------------------------------------------------------- sub findModule { my ($module) = @_; $module =~ s!::|\'!/!g; $module .= '.pm'; foreach my $dir (@INC) { my $path = File::Spec->catfile($dir, $module); return $path if -f $path; } return; } # end findModule
你会这样运行:
perl finddeps.pl scriptToCheck.pl otherScriptToCheck.pl
它打印了运行列出的脚本所需的所有非核心模块的列表.(除非他们使用模块加载进行花哨的技巧,以防止Module :: ExtractUse看到它们.)
您可以在deps.cpantesters.org上使用在线Web服务,该服务将为您提供许多有用的依赖项数据.CPAN上的所有模块都已具有指向依赖关系站点的链接(位于模块页面的右侧).
在过去,我使用了Devel :: Modlist,它非常适合你去
perl -d:Modlist script.pl
获取所需模块的列表.
我有一个基于Make的构建系统,用于我所有的C/C++应用程序(基于PC和各种嵌入式项目),虽然我喜欢能够在新机器上进行顶级构建并验证所有依赖项都在place(我将我的工具链检查到版本控制中:D),我对在我的构建系统中当前没有makefile的解释语言不做同样的事情感到沮丧.
我很想写一个脚本:
在我的修订控制库中搜索扩展名为.pl或.pm的文件
跑perl -d:Modlist
在他们身上(感谢Vagnerr!)
将其连接到所需模块列表
最后将其与已安装模块列表进行比较.
然后,我将执行该脚本作为我的顶级构建的一部分,以便任何构建任何内容的人都知道他们是否拥有运行每个从修订控制获得的perl脚本所需的一切.如果有一些perl脚本它们从不运行并且不想CPAN安装运行它所需的内容,则它们必须从其硬盘驱动器中删除不需要的脚本,因此依赖性检查器无法找到它们.我知道如何在执行'同步'时修改perforce客户端以省略某些子目录,我将不得不想出来进行颠覆......
我建议将依赖检查器设置为搜索pl文件的单个脚本,而不是单个makefile来检查每个脚本的依赖关系,或者基于硬编码的脚本名称列表.如果您选择需要用户操作来检查依赖项的脚本的方法,则人们将忘记执行该操作,因为即使他们不执行依赖性检查,他们也能够运行该脚本.
就像我说的那样,我还没有实现上述内容,但这个问题促使我尝试这样做.我完成后会用我的经验回复.