Domanda

Qualcuno ha qualche suggerimento per un buon approccio alla ricerca di tutte le dipendenze CPAN che potrebbero essere sorte in un progetto di sviluppo su misura. Come tende ad accadere, il tuo ambiente di sviluppo locale raramente corrisponde a quello live e mentre costruisci sempre più progetti, tendi a costruire una libreria locale di moduli installati. Questi quindi ti portano a non notare necessariamente che il tuo ultimo progetto ha un requisito su un modulo non core. Poiché in genere è necessario impacchettare l'intero progetto per la distribuzione in un altro gruppo (nel nostro caso il nostro team operativo), è importante sapere quali moduli dovrebbero essere inclusi nel pacchetto.

Qualcuno ha qualche idea sul problema.

Grazie

Peter

È stato utile?

Soluzione

Ho avuto questo problema da solo. Devel :: Modlist (come suggerito da questa risposta ) adotta un approccio dinamico. Riporta i moduli che sono stati effettivamente caricati durante una particolare esecuzione dello script. In questo modo i moduli vengono caricati con qualsiasi mezzo, ma potrebbero non soddisfare i requisiti condizionali. Cioè, se hai un codice come questo:

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

e $ some_condition sembrano essere falsi, Devel :: Modlist non elencherà Some :: Module come requisito.

Ho deciso di utilizzare invece Module :: ExtractUse . Esegue un'analisi statica, il che significa che catturerà sempre Some :: Module nell'esempio sopra. D'altra parte, non può fare nulla per il codice come:

my $module = "Other::Module";
eval "use $module;";

Naturalmente, è possibile utilizzare entrambi gli approcci e quindi combinare le due liste.

Comunque, ecco la soluzione che mi è venuta in mente:

#! /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 { 

Ho avuto questo problema da solo. Devel :: Modlist (come suggerito da questa risposta ) adotta un approccio dinamico. Riporta i moduli che sono stati effettivamente caricati durante una particolare esecuzione dello script. In questo modo i moduli vengono caricati con qualsiasi mezzo, ma potrebbero non soddisfare i requisiti condizionali. Cioè, se hai un codice come questo:

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

e $ some_condition sembrano essere falsi, Devel :: Modlist non elencherà Some :: Module come requisito.

Ho deciso di utilizzare invece Module :: ExtractUse . Esegue un'analisi statica, il che significa che catturerà sempre Some :: Module nell'esempio sopra. D'altra parte, non può fare nulla per il codice come:

my $module = "Other::Module";
eval "use $module;";

Naturalmente, è possibile utilizzare entrambi gli approcci e quindi combinare le due liste.

Comunque, ecco la soluzione che mi è venuta in mente:

perl finddeps.pl scriptToCheck.pl otherScriptToCheck.pl

Lo faresti come:

<*>

Stampa un elenco di tutti i moduli non core necessari per eseguire gli script elencati. (A meno che non facciano trucchi fantasiosi con il caricamento del modulo che impediscono a Module :: ExtractUse di vederli.)

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

Lo faresti come:

<*>

Stampa un elenco di tutti i moduli non core necessari per eseguire gli script elencati. (A meno che non facciano trucchi fantasiosi con il caricamento del modulo che impediscono a Module :: ExtractUse di vederli.)

Altri suggerimenti

Puoi utilizzare il servizio web online su deps.cpantesters.org che ti fornirà molte utili dipendenze dati. Tutti i moduli su CPAN hanno già il collegamento al sito delle dipendenze (sul lato destro della pagina del modulo).

In passato ho usato Devel :: Modlist che è ragionevolmente buono permettendo andare

perl -d:Modlist script.pl

Per ottenere un elenco dei moduli richiesti.

Ho un sistema di build basato su Make per tutte le mie applicazioni C / C ++ (sia su PC che per vari progetti integrati), e mentre adoro poter fare una build di alto livello su una macchina nuova e verificare tutto dipendenze sono presenti (controllo le mie toolchain per il controllo di revisione: D), sono stato frustrato di non fare lo stesso per i linguaggi interpretati che attualmente non hanno makefile nel mio sistema di compilazione.

Sono tentato di scrivere una sceneggiatura che:

  • cerca nel mio repository di controllo di revisione i file con estensione .pl o .pm
  • esegue perl -d: Modlist su di loro (grazie Vagnerr!)
  • concatenandolo all'elenco dei moduli richiesti
  • e infine confrontandolo con l'elenco dei moduli installati.

Eseguirò quindi quello script come parte della mia build di livello superiore, in modo che chiunque costruisca qualcosa sappia se ha tutto ciò di cui ha bisogno per eseguire ogni script perl ottenuto dal controllo di revisione. Se c'è qualche script perl che non eseguono mai e non vogliono installare CPAN ciò che è richiesto per eseguirlo, dovrebbero rimuovere lo script indesiderato dal loro hard disk, quindi il controllo delle dipendenze non li trova. So come modificare un client perforce per escludere determinate sottodirectory quando si esegue una "sincronizzazione", dovrò capirlo per sovversione ...

Suggerirei di fare del controllo delle dipendenze un singolo script che cerca i file pl, al contrario di un singolo makefile per controllare le dipendenze per ogni script, o basato su un elenco di nomi di script codificato. Se scegli un metodo che richiede che l'utente esegua il controllo di uno script per le dipendenze, le persone dimenticheranno di eseguire quell'azione, poiché saranno in grado di eseguire lo script anche se non eseguono il controllo delle dipendenze.

Come ho detto, non ho ancora implementato quanto sopra, ma questa domanda mi ha spinto a provare a farlo. Ti riporterò indietro con la mia esperienza dopo aver finito.

Il modo "ovvio" - doloroso ma moderatamente efficace - è quello di installare una nuova build di Perl di base in una posizione fuori mano (non la userai in produzione), quindi provare a installare il tuo usando questa versione "vergine" di Perl. Troverai tutte le dipendenze mancanti. La prima volta, questo potrebbe essere doloroso. Dopo la prima volta, avrai già coperto la maggior parte delle dipendenze e sarà notevolmente meno doloroso.

Prendi in considerazione l'esecuzione del tuo repository locale di moduli CPAN, in modo da non dover scaricare sempre il codice. Considera anche come ripulire i moduli non aggiornati.

use Acme::Magic::Pony;

Scherzi a parte. Installerà automaticamente i moduli Perl se risultano mancanti. Vedi Acme :: Magic: : Pony pagina in CPAN.

È un " cavallo imbullonato " risposta ma ho l'abitudine di creare un file Bundle con tutte le mie dipendenze. Quindi quando vado in un nuovo ambiente, lo copio e lo installo.

Ad es. Ho un 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

Inseriscilo in ~ / .cpan / Bundle / (o ovunque risieda il tuo .cpan) e quindi installa 'Bundle :: Baz' come un normale modulo CPAN. In questo modo vengono installati tutti i moduli elencati in " = head1 INDICE " ;.

Ecco una funzione di quickie bash (usando l'eccellente 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
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top