¿Cómo puedo determinar las dependencias de CPAN antes de implementar un proyecto de Perl?

StackOverflow https://stackoverflow.com/questions/240704

Pregunta

¿Alguien tiene alguna sugerencia para un buen enfoque para encontrar todas las dependencias de CPAN que podrían haber surgido en un proyecto de desarrollo a medida? Como suele ser el caso, su entorno de desarrollo local rara vez coincide con su Live y a medida que crea más y más proyectos, tiende a crear una biblioteca local de módulos instalados. Luego, esto lleva a que no se dé cuenta necesariamente de que su último proyecto tiene un requisito en un módulo no principal. Como generalmente existe el requisito de empaquetar todo el proyecto para su implementación en otro grupo (en nuestro caso, nuestro equipo de operaciones), es importante saber qué módulos deben incluirse en el paquete.

¿Alguien tiene alguna idea sobre el problema?

Gracias

Peter

¿Fue útil?

Solución

Yo mismo he tenido este problema. Devel :: Modlist (como sugiere esta respuesta ) adopta un enfoque dinámico. Informa los módulos que realmente se cargaron durante una ejecución particular de su script. Esto atrapa los módulos que están cargados por cualquier medio, pero puede que no detecte los requisitos condicionales. Es decir, si tiene un código como este:

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

y $ some_condition resultan ser falsos, Devel :: Modlist no mostrará Some :: Module como un requisito.

Decidí usar Module :: ExtractUse en su lugar. Hace un análisis estático, lo que significa que siempre detectará Some :: Module en el ejemplo anterior. Por otro lado, no puede hacer nada con el código como:

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

Por supuesto, puedes usar ambos enfoques y luego combinar las dos listas.

De todos modos, aquí está la solución que se me ocurrió:

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

Yo mismo he tenido este problema. Devel :: Modlist (como sugiere esta respuesta ) adopta un enfoque dinámico. Informa los módulos que realmente se cargaron durante una ejecución particular de su script. Esto atrapa los módulos que están cargados por cualquier medio, pero puede que no detecte los requisitos condicionales. Es decir, si tiene un código como este:

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

y $ some_condition resultan ser falsos, Devel :: Modlist no mostrará Some :: Module como un requisito.

Decidí usar Module :: ExtractUse en su lugar. Hace un análisis estático, lo que significa que siempre detectará Some :: Module en el ejemplo anterior. Por otro lado, no puede hacer nada con el código como:

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

Por supuesto, puedes usar ambos enfoques y luego combinar las dos listas.

De todos modos, aquí está la solución que se me ocurrió:

perl finddeps.pl scriptToCheck.pl otherScriptToCheck.pl

Ejecutarías esto así:

<*>

Imprime una lista de todos los módulos no básicos necesarios para ejecutar los scripts listados. (A menos que realicen trucos sofisticados con la carga de módulos que impiden que Module :: ExtractUse los vea).

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

Ejecutarías esto así:

<*>

Imprime una lista de todos los módulos no básicos necesarios para ejecutar los scripts listados. (A menos que realicen trucos sofisticados con la carga de módulos que impiden que Module :: ExtractUse los vea).

Otros consejos

Puede utilizar el servicio web en línea en deps.cpantesters.org que le proporcionará muchas dependencias útiles datos. Todos los módulos en CPAN ya tienen el enlace al sitio de dependencia (en el lado derecho de la página del módulo).

En el pasado he usado Devel :: Modlist que es razonablemente bueno. tu debes ir

perl -d:Modlist script.pl

Para obtener una lista de los módulos necesarios.

Tengo un sistema de compilación basado en Make para todas mis aplicaciones de C / C ++ (tanto para PC como para varios proyectos integrados), y aunque me encanta poder realizar una compilación de alto nivel en una máquina nueva y verificar todo las dependencias están en su lugar (verifico mis cadenas de herramientas en el control de revisión: D), me siento frustrado por no hacer lo mismo con los idiomas interpretados que actualmente no tienen makefile en mi sistema de compilación.

Estoy tentado a escribir un script que:

  • busca en mi repositorio de control de revisiones los archivos con la extensión .pl o .pm
  • ejecuta perl -d: Modlist en ellos (gracias Vagnerr!)
  • concatenándolo a la lista de módulos necesarios
  • y finalmente comparándolo con la lista de módulos instalados.

Luego ejecutaría ese script como parte de mi compilación de nivel superior, de modo que cualquiera que construya algo sabrá si tiene todo lo que necesita para ejecutar cada script perl que obtuvo del control de revisión. Si hay alguna secuencia de comandos de Perl que nunca ejecutan y no quieren que CPAN instale lo que se requiere para ejecutarla, tendrían que eliminar la secuencia de comandos no deseada de su disco duro, por lo que el verificador de dependencias no puede encontrarlos. Sé cómo modificar un cliente forzado para dejar de lado ciertos subdirectorios cuando haces una 'sincronización', tendré que resolver eso para la subversión ...

Yo sugeriría que el verificador de dependencias sea un solo script que busque archivos pl, en lugar de un makefile individual para verificar las dependencias de cada script, o que esté basado en una lista de nombres de script codificados. Si elige un método que requiere la acción del usuario para que un script verifique las dependencias, las personas se olvidarán de realizar esa acción, ya que podrán ejecutar el script incluso si no hacen la verificación de dependencia.

Como dije, aún no he implementado lo anterior, pero esta pregunta me ha llevado a intentar hacerlo. Volveré a publicar con mi experiencia cuando haya terminado.

La forma "obvia", dolorosa pero moderadamente efectiva, es instalar una versión nueva de Perl base en alguna ubicación apartada (no vas a usar esto en producción) y luego intentar instalar tu Módulo usando esta versión 'virgen' de Perl. Encontrarás todas las dependencias faltantes. La primera vez, esto podría ser doloroso. Después de la primera vez, ya tendrá la mayoría de las dependencias cubiertas, y será mucho menos dolorosa.

Considere ejecutar su propio repositorio local de módulos CPAN, para que no siempre tenga que descargar el código. También considere cómo limpiar los módulos obsoletos.

use Acme::Magic::Pony;

En serio. Se instalarán automáticamente los módulos de Perl si aparecen faltantes. Consulte Acme :: Magic: : Pony página en CPAN.

Es un " caballo que está atornillado " Respondo, pero tengo la costumbre de crear un archivo Bundle con todas mis dependencias. Por lo tanto, cuando voy a un nuevo entorno, simplemente lo copio y lo instalo.

Por ej. Tengo 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

Ponga esto en ~ / .cpan / Bundle / (o donde viva su .cpan) y luego instale 'Bundle :: Baz' como un módulo CPAN normal. Esto instala todos los módulos listados en " = head1 CONTENTS " ;.

Aquí hay una función rápida de bash (usando la excelente 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
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top