如何找到我的 Perl 脚本的模块依赖项?
Posted
技术标签:
【中文标题】如何找到我的 Perl 脚本的模块依赖项?【英文标题】:How do I find the module dependencies of my Perl script? 【发布时间】:2010-09-26 09:52:32 【问题描述】:我希望其他开发人员运行我编写的 Perl 脚本。该脚本使用许多 CPAN 模块,必须先安装这些模块才能运行该脚本。是否可以使脚本(或perl
二进制文件)转储所有缺失模块的列表?当我尝试运行脚本时,Perl 会打印出丢失模块的名称,但这很冗长,并且不会一次列出所有丢失的模块。我想做类似的事情:
$ cpan -i `said-script --list-deps`
甚至:
$ list-deps said-script > required-modules # on my machine
$ cpan -i `cat required-modules` # on his machine
有简单的方法吗?这不是一个表演障碍,但我想让其他开发人员的生活更轻松。 (所需的模块分散在几个文件中,因此我很难手动列出列表而不遗漏任何内容。我知道PAR,但对于我想要的来说似乎有点太复杂了。)
更新:谢谢,Manni,这样就可以了。我不知道%INC
,我只知道@INC
。我解决了这样的问题:
print join("\n", map s|/|::|g; s|\.pm$||; $_ keys %INC);
打印出来的:
Moose::Meta::TypeConstraint::Registry
Moose::Meta::Role::Application::ToClass
Class::C3
List::Util
Imager::Color
…
看起来这会奏效。
【问题讨论】:
【参考方案1】:您可以在脚本末尾转储%INC
。它将包含所有使用和必需的模块。但是,当然,这只有在您没有条件地需要模块时才有用(如果 $bar 则需要 Foo)。
【讨论】:
【参考方案2】:查看Module::ScanDeps 和它附带的“scandeps.pl”实用程序。它可以在编译或运行程序后对代码的依赖关系以及 %INC 转储进行静态(和递归)分析。
请注意,静态源扫描总是在包含太多依赖项的情况下出错。 (它是 PAR 使用的依赖扫描器,旨在对最终用户最简单。)
最后,您可以选择将脚本作为 CPAN 分发版分发。这听起来比实际上要复杂得多。您可以使用Module::Starter 之类的东西来设置暂定 App::YourScript 分发的基本框架。将您的脚本放在 bin/ 子目录中并编辑 Makefile.PL 以引用您的所有 direct 依赖项。然后,对于分发你做:
-
perl Makefile.PL
制作
制作分布
最后一步生成一个不错的 App-YourScript-VERSION.tar.gz 现在,当客户端想要安装所有依赖项时,他会执行以下操作:
-
正确设置 CPAN 客户端。只需运行它并回答问题。但无论如何你已经需要了。
"tar -xz App-YourScript-VERSION.tar.gz && cd App-YourScript-VERSION"
运行“cpan”。
CPAN 客户端现在将自动安装所有直接依赖项和这些发行版的依赖项。根据您的设置方式,它会自动递归地遵循先决条件,或者每次都以 y/n 提示。
作为一个例子,您可以查看 CPAN 上的一些 App::* 发行版。我认为 App::Ack 是一个很好的例子。可能是我的 CPAN 目录 (SMUELLER) 中的 App::* 发行版之一。
【讨论】:
不,静态源扫描并不总是因为包含太多依赖项而出错。它也可能会错过像eval "require $module"
这样的东西,其中$module
是在运行时根据某些标准计算的。【参考方案3】:
对于快速且不经常使用的情况,%INC
是最好的选择。如果您必须通过持续集成测试或更健壮的方式来实现这一点,还有其他一些工具可以提供帮助。
Steffen 已经提到了 Module::ScanDeps。
Test::Prereq 中的代码执行此操作,但它有一个附加层,可确保您的 Makefile.PL 或 Build.PL 将它们列为依赖项。如果你创建了scripts look like a normal Perl distribution,那么检查新的依赖关系就变得相当容易了;只需再次运行测试套件。
除此之外,您还可以使用诸如Module::Extract::Use 之类的工具,该工具会解析静态代码以查找 use 和 require 语句(尽管它不会在字符串 eval 中找到它们)。这让你得到你告诉你的脚本加载的模块。 此外,一旦您知道自己加载了哪些模块,就可以将其与 David Cantrell 的 CPANdeps 工具结合使用,该工具已经为大多数 CPAN 模块创建了依赖关系树。
请注意,您还必须考虑可选功能。在这种情况下,您的代码我没有它们,但有时您在需要时才加载模块:
子富 需要酒吧; # 在我们需要使用之前不要加载 ……如果您在试运行或测试中不使用该功能,您将不会看到该功能需要 Bar。当一个模块在不同的环境(例如,mod_perl 或 Windows 等)中加载一组不同的依赖模块时,也会出现类似的问题。
没有一种很好的自动化方式来测试这样的可选功能,以便您可以获取它们的依赖项。不过,我认为这应该在我的待办事项列表中,因为这听起来是个有趣的问题。
【讨论】:
【参考方案4】:今天我使用Dist::Zilla 将我的Perl 应用程序开发为CPAN-like distributions,它可以通过AutoPrereq 插件处理依赖关系。这个领域另一个有趣的代码是carton。
【讨论】:
【参考方案5】:Dist::Zilla 及其 AutoPrereqs 插件使用该领域的另一个工具是Perl::PrereqScanner。它安装了一个scan-perl-prereqs
程序,该程序将使用 PPI 和一些插件来搜索大多数类型的 prereq 声明,使用您定义的最低版本。一般来说,我建议这种过度扫描%INC
,这可能会带来虚假需求并忽略版本。
【讨论】:
这比scandeps
更适合我的工作流程。它只给了我故意包含的名字。 (子依赖项大多不感兴趣,因为现代安装程序会为您处理它们。)以上是关于如何找到我的 Perl 脚本的模块依赖项?的主要内容,如果未能解决你的问题,请参考以下文章
如果在它使用的模块中引发异常,我如何防止我的 perl 脚本终止?