Question

Quelqu'un a-t-il des suggestions pour une bonne approche pour trouver toutes les dépendances de CPAN pouvant survenir dans un projet de développement sur mesure? Comme cela a tendance à être le cas, votre environnement de développement local correspond rarement à votre environnement réel et, à mesure que vous construisez de plus en plus de projets, vous avez tendance à constituer une bibliothèque locale de modules installés. Celles-ci ne vous font alors pas nécessairement remarquer que votre dernier projet a une exigence sur un module non essentiel. Comme il est généralement nécessaire de regrouper l'ensemble du projet en vue de son déploiement dans un autre groupe (dans notre cas, notre équipe des opérations), il est important de savoir quels modules doivent être inclus dans le package.

Quelqu'un at-il une idée du problème?

Merci

Peter

Était-ce utile?

La solution

J'ai eu ce problème moi-même. Devel :: Modlist (comme suggéré par cette réponse ) adopte une approche dynamique. Il indique les modules qui ont été chargés lors d'une exécution particulière de votre script. Cela intercepte les modules chargés par n'importe quel moyen, mais ne répond pas aux exigences conditionnelles. Autrement dit, si vous avez un code comme celui-ci:

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

et $ some_condition sont faux, Devel :: Modlist ne listera pas Some :: Module en tant qu'exigence.

J'ai décidé d'utiliser plutôt Module :: ExtractUse . Il effectue une analyse statique, ce qui signifie qu'il capturera toujours Some :: Module dans l'exemple ci-dessus. Par contre, il ne peut rien faire avec le code tel que:

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

Bien sûr, vous pouvez utiliser les deux approches, puis combiner les deux listes.

Quoi qu'il en soit, voici la solution que j'ai proposée:

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

J'ai eu ce problème moi-même. Devel :: Modlist (comme suggéré par cette réponse ) adopte une approche dynamique. Il indique les modules qui ont été chargés lors d'une exécution particulière de votre script. Cela intercepte les modules chargés par n'importe quel moyen, mais ne répond pas aux exigences conditionnelles. Autrement dit, si vous avez un code comme celui-ci:

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

et $ some_condition sont faux, Devel :: Modlist ne listera pas Some :: Module en tant qu'exigence.

J'ai décidé d'utiliser plutôt Module :: ExtractUse . Il effectue une analyse statique, ce qui signifie qu'il capturera toujours Some :: Module dans l'exemple ci-dessus. Par contre, il ne peut rien faire avec le code tel que:

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

Bien sûr, vous pouvez utiliser les deux approches, puis combiner les deux listes.

Quoi qu'il en soit, voici la solution que j'ai proposée:

perl finddeps.pl scriptToCheck.pl otherScriptToCheck.pl

Vous exécuteriez ceci comme:

<*>

Il imprime une liste de tous les modules non essentiels nécessaires à l’exécution des scripts répertoriés. (Sauf s'ils réalisent des astuces avec le chargement de module qui empêchent Module :: ExtractUse de les voir.)

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

Vous exécuteriez ceci comme:

<*>

Il imprime une liste de tous les modules non essentiels nécessaires à l’exécution des scripts répertoriés. (Sauf s'ils réalisent des astuces avec le chargement de module qui empêchent Module :: ExtractUse de les voir.)

Autres conseils

Vous pouvez utiliser le service Web en ligne à l'adresse deps.cpantesters.org qui vous fournira de nombreuses dépendances utiles. Les données. Tous les modules de CPAN ont déjà le lien vers le site de dépendance (à droite de la page du module).

Dans le passé, j’utilisais Devel :: Modlist , ce qui est raisonnablement bon pour permettre vous aller

perl -d:Modlist script.pl

Pour obtenir une liste des modules requis.

J'ai un système de construction Make basé sur toutes mes applications C / C ++ (sur PC ainsi que sur divers projets embarqués), et j'aime être capable de construire une version de haut niveau sur une nouvelle machine et de vérifier tout des dépendances sont en place (je vérifie mes chaînes d'outils dans le contrôle de révision: D), j'ai été frustré de ne pas faire la même chose pour les langages interprétés qui n'ont actuellement aucun fichier makefile dans mon système de construction.

Je suis tenté d'écrire un script qui:

  • recherche dans mon référentiel de contrôle de révision les fichiers portant l'extension .pl ou .pm
  • exécute perl -d: Modlist sur eux (merci Vagnerr!)
  • le concaténant avec la liste des modules requis
  • et enfin en le comparant à la liste des modules installés.

J'exécuterais ensuite ce script dans le cadre de ma construction de niveau supérieur, afin que toute personne qui construit quelque chose sache si elle dispose de tout le matériel nécessaire pour exécuter chaque script Perl obtenu du contrôle de révision. S'il y a des scripts Perl qu'ils n'exécutent jamais et ne souhaitent pas que CPAN installe ce qui est nécessaire pour l'exécuter, ils devront supprimer le script indésirable de leur disque dur afin que le vérificateur de dépendance ne les trouve pas. Je sais comment modifier un client obligé pour qu'il supprime certains sous-répertoires lorsque vous effectuez une "synchronisation". Je vais devoir le comprendre pour la subversion ...

Je suggèrerais de faire du vérificateur de dépendance un script unique qui recherche des fichiers pl, par opposition à un fichier Make individuel pour vérifier les dépendances de chaque script, ou basé sur une liste codée en dur de noms de script. Si vous choisissez une méthode nécessitant une action de la part d'un utilisateur pour qu'un script soit vérifié pour les dépendances, les utilisateurs oublieront d'exécuter cette action car ils pourront exécuter le script même s'ils ne font pas la vérification des dépendances.

Comme je l'ai dit, je n'ai pas encore implémenté ce qui précède, mais cette question m'a incité à essayer de le faire. Je reviendrai avec mon expérience une fois que j'aurai terminé.

La méthode "évidente" - douloureuse mais modérément efficace - consiste à installer une toute nouvelle version de Perl de base dans un emplacement éloigné (vous ne l'utiliserez pas en production), puis d'essayer d'installer votre module utilisant cette version "vierge" de Perl. Vous trouverez toutes les dépendances manquantes. La première fois, cela pourrait être douloureux. Après la première fois, vous aurez déjà couvert la majorité des dépendances et ce sera beaucoup moins pénible.

Pensez à exécuter votre propre référentiel local de modules CPAN afin de ne pas toujours télécharger le code. Pensez également à la façon dont vous nettoyez les modules obsolètes.

use Acme::Magic::Pony;

Sérieusement. Il installera automatiquement les modules Perl s'ils s'avèrent manquants. Voir le Acme :: Magic: : Page Poney dans CPAN.

C'est un "cheval qui est boulonné". mais j’ai l’habitude de créer un fichier Bundle avec toutes mes dépendances. Ainsi, lorsque je vais dans un nouvel environnement, je le copie et l’installe.

Par exemple. J'ai 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

Mettez ceci dans ~ / .cpan / Bundle / (ou où que vive votre .cpan) puis installez 'Bundle :: Baz' comme un module CPAN normal. Ceci installe alors tous les modules listés sous "= head1 CONTENTS".

Voici une fonction quickie bash (utilisant l'excellent 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
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top