对于查找定制开发项目中可能出现的所有 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 <perl at cjmweb.net>
#
# 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 { 

我自己也遇到过这个问题。 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;";

当然,您可以使用这两种方法然后合并两个列表。

无论如何,这是我提出的解决方案:

perl finddeps.pl scriptToCheck.pl otherScriptToCheck.pl

你可以这样运行:

<*>

它打印运行所列脚本所需的所有非核心模块的列表。 (除非他们使用模块加载来防止Module :: ExtractUse看到它们。)

=> 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

你可以这样运行:

<*>

它打印运行所列脚本所需的所有非核心模块的列表。 (除非他们使用模块加载来防止Module :: ExtractUse看到它们。)

其他提示

您可以在 deps.cpantesters.org 上使用在线网络服务,它将为您提供许多有用的依赖关系数据。 CPAN上的所有模块都已具有指向依赖关系站点的链接(位于模块页面的右侧)。

过去我使用了 Devel :: Modlist ,这是一个相当不错的选择你去吧

perl -d:Modlist script.pl

获取所需模块的列表。

我有一个基于 Make 的构建系统,适用于我的所有 C/C++ 应用程序(基于 PC 的应用程序和各种嵌入式项目),虽然我喜欢能够在新机器上进行顶级构建并验证所有依赖项都在地方(我将我的工具链检查到修订控制:D),我一直很沮丧,因为我没有对当前构建系统中没有 makefile 的解释语言执行相同的操作。

我很想写一个脚本:

  • 在我的修订控制存储库中搜索扩展名为 .pl 或 .pm 的文件
  • 运行 perl -d:Modlist 在他们身上(感谢瓦格纳!)
  • 将其连接到所需模块的列表
  • 最后将其与已安装模块的列表进行比较。

然后,我会执行该脚本作为我的顶级构建的一部分,以便任何构建任何东西的人都会知道他们是否拥有运行从修订控制获得的每个 perl 脚本所需的一切。如果有一些 Perl 脚本他们从未运行并且不想 CPAN 安装运行它所需的内容,他们必须从硬盘驱动器中删除不需要的脚本,这样依赖项检查器就无法找到它们。我知道如何修改 perforce 客户端,以便在执行“同步”时省略某些子目录,我必须弄清楚这一点以进行颠覆......

我建议将依赖性检查器设置为搜索 pl 文件的单个脚本,而不是使用单独的 makefile 来检查每个脚本的依赖性,或者基于脚本名称的硬编码列表。如果您选择的方法需要用户操作来检查脚本的依赖关系,那么人们将忘记执行该操作,因为即使他们不进行依赖关系检查,他们也能够运行该脚本。

就像我说的,我还没有实现上述内容,但这个问题促使我尝试这样做。完成后我会回复我的经验。

'明显'的方式 - 痛苦但适度有效 - 是在一些偏僻的位置安装一个全新的Perl基础版本(你不打算在生产中使用它),然后尝试安装你的模块使用这个'处女'版本的Perl。您将找到所有缺少的依赖项。第一次,这可能是痛苦的。在第一次之后,你已经覆盖了大多数依赖项,并且它将不那么痛苦。

考虑运行您自己的CPAN模块本地存储库 - 这样您就不必总是下载代码了。还要考虑如何清理过时的模块。

use Acme::Magic::Pony;

严重。如果它们丢失,它将自动安装Perl模块。请参阅 Acme :: Magic: :CPAN中的Pony 页面。

它是一匹“用螺栓固定的马”。回答,但我养成了创建一个包含所有依赖项的Bundle文件的习惯。因此,当我进入一个新环境时,我只需将其复制并安装即可。

例如。我有一个Baz.pm

package Bundle::Baz;
$VERSION = '0.1';
1;
__END__
=head1 NAME
Bundle::Baz
=head1 SYNOPSIS
perl -MCPAN -e 'install Bundle::Baz'
=head1 CONTENTS
# Baz's modules
XML::Twig
XML::Writer
Perl6::Say
Moose

将它放在〜/ .cpan / Bundle /(或.cpan所在的任何地方),然后像普通的CPAN模块一样安装'Bundle :: Baz'。然后安装“= head1 CONTENTS”下列出的所有模块。

这是一个快速bash功能(使用优秀的确认):

# find-perl-module-use <directory> (lib/ by default)
function find-perl-module-use() {
    dir=${1:-lib}
    ack '^\s*use\s+.*;\s* $dir | awk '{ print $2 }' | sed 's/();\?$\|;$//' | sort | uniq
    ack '^\s*use\s+base\s+.*;\s* $dir | awk '{ print $3 }' | sed 's/();\?$\|;$//' | sort | uniq
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top