2008-10-27 69 views
11

有沒有人有任何建議,找到一個好的方法來找到可能在定製開發項目中出現的所有CPAN依賴項。情況往往是這樣的,你的本地開發環境很少與你的現有開發環境相匹配,並且當你構建越來越多的項目時,你往往會建立一個已安裝模塊的本地庫。這些會導致您不一定會注意到您的最新項目對非核心模塊有要求。由於通常需要將整個項目打包並部署到另一個組(本例中爲我們的操作團隊),因此瞭解包中應包含哪些模塊很重要。如何在部署Perl項目之前確定CPAN依賴關係?

有沒有人對這個問題有任何認識。

感謝

彼得

回答

13

我自己有這個問題。 Devel::Modlist(如this answer建議)採取動態方法。它報告在特定腳本運行期間實際加載的模塊。這會捕獲以任何方式加載的模塊,但它可能不符合條件要求。也就是說,如果你有這樣的代碼:

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 { $_ => 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看到它們。)

9

在我用Devel::Modlist這是相當不錯的,允許過去,你去

perl -d:Modlist script.pl 

獲得所需要的模塊的列表。

11

您可以使用在線網絡服務deps.cpantesters.org,它將爲您提供許多有用的依賴關係數據。 CPAN上的所有模塊都已鏈接到依賴站點(位於模塊頁面的右側)。

3

'明顯'的方式 - 痛苦但適度有效 - 是在某些位置安裝一個全新的基本Perl版本(您不打算在生產中使用此版本),然後嘗試安裝你的模塊使用這個'處女'版本的Perl。你會發現所有缺失的依賴關係。第一次,這可能是痛苦的。在第一次之後,你已經擁有了大部分的依賴關係,並且它將不那麼痛苦。

考慮運行您自己的本地CPAN模塊存儲庫 - 以便您不必總是下載代碼。還要考慮如何清理過時的模塊。

5

我的所有C/C++應用程序(基於PC和各種嵌入式項目)都有基於Make的構建系統,而且我喜歡能夠在新機器上進行頂級構建並驗證所有的依賴關係都已到位(我檢查了我的工具鏈到版本控制:D),但對於目前在我的構建系統中沒有makefile的解釋語言,我一直感到沮喪。

我很想寫一個腳本:

  • 搜索我的版本控制庫與他們的.pl和.pm的擴展
  • 運行perl -d:Modlist文件
  • (感謝Vagnerr!)將其連接到所需模塊列表
  • 並最終將其與已安裝模塊的列表進行比較。

我然後執行該腳本作爲我的頂級版本的一部分,使任何人都建設任何事情都會知道,如果他們有他們需要跑,他們從版本控制了每一個perl腳本的一切。如果有一些Perl腳本永遠不會運行,並且不希望CPAN安裝運行它所需的內容,則必須從硬盤中刪除不需要的腳本,以便依賴檢查程序找不到它們。我知道如何修改perforce客戶端,以便在執行「同步」時省略某些子目錄,但我必須爲顛覆計算出來......

我建議做檢查,搜索PL文件,而不是一個單獨的makefile檢查依賴性爲每個腳本,或基於腳本名稱的硬編碼列表上的單個腳本的依賴。如果您選擇一種需要用戶操作來檢查依賴項的腳本的方法,那麼人們將會忘記執行該操作,因爲即使他們不執行依賴項檢查,他們也能夠運行該腳本。

就像我說的,我還沒有實現上面還,但這個問題已經促使我嘗試這樣做。完成後,我會以我的經驗回覆。

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 /包/(或任何你.cpan生活),然後安裝「捆綁::巴茲」像一個正常的CPAN模塊將這個。然後安裝「= head1 CONTENTS」下列出的所有模塊。

3
use Acme::Magic::Pony; 

說真的。它會自動安裝Perl模塊,如果它們丟失。請參閱CPAN中的Acme::Magic::Pony頁面。

+0

有趣的,但如果你嘗試和使用,在現場的商業環境中,運營團隊將是一個有點不高興你,想看看你是否意識到穩定性和安全性的概念:-) – Vagnerr 2008-11-01 20:24:10

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 
}