13

オーダーメイドの開発プロジェクトで発生した可能性のあるすべてのCPAN依存関係を見つけるための良いアプローチについて誰かが提案を持っていますか?よくあることですが、ローカル開発環境が実際の開発環境と一致することはめったになく、プロジェクトを構築するにつれて、インストールされたモジュールのローカルライブラリを構築する傾向があります。これらは、最新のプロジェクトに非コアモジュールの要件があることに必ずしも気付かないことにつながります。通常、プロジェクト全体をパッケージ化して別のグループ(この場合は運用チーム)に展開する必要があるため、パッケージに含めるモジュールを知ることが重要です。

誰かが問題について何か洞察を持っていますか?

ありがとう

ピーター

4

8 に答える 8

14

私は自分でこの問題を抱えていました。 Devel::Modlist (この回答で示唆されているように) は動的なアプローチを採用しています。スクリプトの特定の実行中に実際にロードされたモジュールを報告します。これは何らかの方法でロードされたモジュールをキャッチしますが、条件付きの要件をキャッチできない場合があります。つまり、次のようなコードがある場合:

if ($some_condition) { require Some::Module }

$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 { $_ => 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 がそれらを認識できないように、モジュールの読み込みで巧妙なトリックを実行しない限り。)

于 2008-10-27T20:57:38.290 に答える
11

多くの有用な依存関係データを提供するdeps.cpantesters.orgのオンライン Web サービスを使用できます。CPAN のすべてのモジュールには、既に依存関係サイトへのリンクがあります (モジュール ページの右側にあります)。

于 2008-10-27T17:39:43.977 に答える
10

過去に私はDevel::Modlistを使用しました。

perl -d:Modlist script.pl

必要なモジュールのリストを取得します。

于 2008-10-27T17:25:59.183 に答える
5

私はすべての C/C++ アプリケーション (PC ベースとさまざまな組み込みプロジェクトの両方) 用に Make ベースのビルド システムを使用しています。場所 (ツールチェーンをリビジョン管理にチェックインします:D)、ビルドシステムに現在 makefile がないインタープリター言語に対して同じことをしないことに不満を感じていました。

次のようなスクリプトを書きたくなりました。

  • リビジョン管理リポジトリで拡張子が .pl または .pm のファイルを検索します
  • それらで実行perl -d:Modlistされます(Vagnerrに感謝します!)
  • 必要なモジュールのリストに連結する
  • 最後に、インストールされているモジュールのリストと比較します。

次に、そのスクリプトを最上位ビルドの一部として実行します。これにより、何かをビルドする人は、リビジョン管理から取得したすべての perl スクリプトを実行するために必要なものがすべて揃っているかどうかを知ることができます。実行したことがなく、実行に必要なものを CPAN インストールしたくない perl スクリプトがある場合、不要なスクリプトをハードドライブから削除する必要があるため、依存関係チェッカーはそれらを見つけることができません。「同期」を行うときに特定のサブディレクトリを除外するようにperforceクライアントを変更する方法を知っています。subversionのためにそれを理解する必要があります...

依存関係チェッカーを、各スクリプトの依存関係をチェックするための個別のメイクファイルとは対照的に、またはスクリプト名のハードコーディングされたリストに基づいて、pl ファイルを検索する単一のスクリプトにすることをお勧めします。スクリプトの依存関係をチェックするためにユーザーの操作が必要な方法を選択すると、依存関係のチェックを行わなくてもスクリプトを実行できるため、ユーザーはその操作を忘れてしまいます。

私が言ったように、私はまだ上記を実装していませんが、この質問は私にそうしようとするよう促しました. 終わったら、私の経験を元に投稿します。

于 2008-10-27T18:19:17.203 に答える
3

「明白な」方法 - 苦痛ではあるが適度に効果的 - は、ベース Perl の真新しいビルドを邪魔にならない場所にインストールし (これを本番環境では使用しない)、次にこれを使用してモジュールをインストールしようとすることです。 Perl の「バージン」バージョン。不足しているすべての依存関係が見つかります。初めて、これは痛いかもしれません。1 回目以降は、依存関係の大部分が既にカバーされているため、負担が大幅に軽減されます。

コードを常にダウンロードする必要がないように、CPAN モジュールの独自のローカル リポジトリを実行することを検討してください。また、古いモジュールをクリーンアップする方法も検討してください。

于 2008-10-27T17:40:01.510 に答える
3
use Acme::Magic::Pony;

真剣に。Perl モジュールが見つからない場合、自動インストールします。CPANのAcme::Magic::Ponyページを参照してください。

于 2008-10-28T22:43:18.200 に答える
2

それは「ボルトで固定された馬」の答えですが、すべての依存関係を含むバンドルファイルを作成する習慣があります。したがって、新しい環境に行くときは、それをコピーしてインストールするだけです。

たとえば。私は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」の下にリストされているすべてのモジュールがインストールされます。

于 2008-10-27T19:08:43.610 に答える
1

これは急ごしらえの 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
}
于 2008-10-28T22:48:53.073 に答える