Perlプロジェクトを展開する前にCPANの依存関係を判断するにはどうすればよいですか?
-
04-07-2019 - |
質問
オーダーメイドの開発プロジェクトで発生した可能性のあるすべてのCPAN依存関係を見つけるための優れたアプローチについて、提案はありますか?よくあることですが、ローカルの開発環境は実際のライブ環境とほとんど一致しません。また、プロジェクトを構築するにつれて、インストールされたモジュールのローカルライブラリを構築する傾向があります。これらは、最新のプロジェクトが非コアモジュールの要件を持っていることに必ずしも気付かないことにつながります。通常、プロジェクト全体を別のグループ(この場合は運用チーム)に展開するためにパッケージ化する必要があるため、パッケージに含めるモジュールを知ることが重要です。
誰でも問題についての洞察を持っていますか。
ありがとう
ピーター
解決
自分でこの問題を抱えています。 Devel :: Modlist (この回答)は動的なアプローチを取ります。スクリプトの特定の実行中に実際にロードされたモジュールを報告します。これは、何らかの手段でロードされたモジュールをキャッチしますが、条件付き要件をキャッチしない場合があります。つまり、次のようなコードがある場合:
if ($some_condition) { require Some::Module }
and $ some_condition
はたまたまfalseです。 Devel :: Modlist
は Some :: Module
を要件としてリストしません。
代わりに Module :: ExtractUse を使用することにしました。静的分析を行います。つまり、上記の例では常に Some :: Module
をキャッチします。一方、次のようなコードについては何もできません:
my $module = "Other::Module";
eval "use $module;";
もちろん、両方のアプローチを使用してから、2つのリストを組み合わせることができます。
とにかく、ここに私が思いついた解決策があります:
#! /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 }
and $ some_condition
はたまたまfalseです。 Devel :: Modlist
は Some :: Module
を要件としてリストしません。
>
代わりに Module :: ExtractUse を使用することにしました。静的分析を行います。つまり、上記の例では常に Some :: Module
をキャッチします。一方、次のようなコードについては何もできません:
my $module = "Other::Module";
eval "use $module;";
もちろん、両方のアプローチを使用してから、2つのリストを組み合わせることができます。
とにかく、ここに私が思いついた解決策があります:
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 のオンラインWebサービスを使用すると、多くの有用な依存関係を提供できます。データ。 CPAN上のすべてのモジュールには、既に依存関係サイトへのリンクがあります(モジュールページの右側)。
すべてのC / C ++アプリケーション(PCベースとさまざまな組み込みプロジェクトの両方)にMakeベースのビルドシステムがあり、新しいマシンでトップレベルビルドを実行してすべてを検証できることが大好き依存関係が整っているため(リビジョン管理のためにツールチェーンをチェックします:D)、ビルドシステムに現在makefileがないインタープリター言語に対して同じことをしないことにイライラしています。
次のようなスクリプトを書きたいと思います:
- .plまたは.pm拡張子を持つファイルのリビジョン管理リポジトリを検索します
- それらに対して
perl -d:Modlist
を実行します(Vagnerrに感謝!) - 必要なモジュールのリストに連結
- 最後にインストール済みモジュールのリストと比較します。
次に、トップレベルビルドの一部としてそのスクリプトを実行します。これにより、何かをビルドする人は、リビジョン管理から取得したすべてのperlスクリプトを実行するために必要なものがすべて揃っているかどうかがわかります実行されないperlスクリプトがあり、実行に必要なものをCPANにインストールしたくない場合、ハードドライブから不要なスクリプトを削除する必要があるため、依存関係チェッカーはそれらを見つけることができません。 「同期」を実行するときに特定のサブディレクトリを除外するようにPERFORCEクライアントを変更する方法を知っていますが、Subversionではそれを把握する必要があります...
依存関係チェッカーを、plファイルを検索する単一のスクリプトにすることをお勧めします。各スクリプトの依存関係をチェックする個別のメイクファイルや、スクリプト名のハードコードリストに基づくものではありません。スクリプトに依存関係をチェックさせるためにユーザーアクションが必要な方法を選択した場合、依存関係チェックを行わなくてもスクリプトを実行できるため、ユーザーはそのアクションの実行を忘れます。
私が言ったように、私はまだ上記を実装していませんが、この質問はそうするように私を促しました。完了したら、経験を投稿します。
「明らかな」方法-痛みを伴うが中程度の効果-は、ベースPerlの新しいビルドをある場所から離れた場所にインストールし(本番環境では使用しない)、インストールすることです。この「バージン」バージョンのPerlを使用するモジュール。不足している依存関係がすべて見つかります。初めて、これは苦痛かもしれません。初回以降は、依存関係の大部分がすでにカバーされているため、痛みは大幅に軽減されます。
CPANモジュールの独自のローカルリポジトリを実行することを検討してください-常にコードをダウンロードする必要はありません。また、古くなったモジュールをクリーンアップする方法も検討してください。
use Acme::Magic::Pony;
真剣に。 Perlモジュールが見つからない場合は、Perlモジュールが自動インストールされます。 Acme :: Magicを参照してください。 :CPANのポニーページ。
「ボルトで固定された馬」です答えますが、すべての依存関係を含むバンドルファイルを作成する習慣があります。したがって、新しい環境に移動するときは、コピーしてインストールするだけです。
たとえば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'をインストールします。これにより、&quot; = head1 CONTENTS&quot;の下にリストされているすべてのモジュールがインストールされます。
クイックキーbash関数があります(優れた ack を使用):
# 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
}