2008-10-27 20 views
11

¿Alguien tiene alguna sugerencia para un buen enfoque para encontrar todas las dependencias de CPAN que puedan haber surgido en un proyecto de desarrollo a medida? Como suele ser el caso, su entorno de desarrollo local rara vez coincide con su entorno real y a medida que construye más y más proyectos, tiende a construir una biblioteca local de módulos instalados. Esto te lleva a no necesariamente notar que tu último proyecto tiene un requisito en un módulo no principal. Dado que generalmente es necesario empaquetar todo el proyecto para su implementación en otro grupo (en nuestro caso, nuestro equipo de operaciones), es importante saber qué módulos se deben incluir en el paquete.¿Cómo puedo determinar las dependencias de CPAN antes de implementar un proyecto de Perl?

¿Alguien tiene alguna idea sobre el problema.

Gracias

Peter

Respuesta

13

He tenido este problema yo mismo. Devel::Modlist (según lo sugerido por this answer) adopta un enfoque dinámico. Informa los módulos que se cargaron realmente durante una ejecución particular de su secuencia de comandos. Esto capta los módulos que se cargan por cualquier medio, pero es posible que no capte los requisitos condicionales. Es decir, si usted tiene un código como éste:

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

y $some_condition resulta ser falsa, Devel::Modlist no la lista de Some::Module como 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 se puede hacer nada al respecto código como:

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

Por supuesto, se puede 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 { $_ => 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 

que había corrido esto como:

perl finddeps.pl scriptToCheck.pl otherScriptToCheck.pl 

Se imprime una lista de todos los módulos no esenciales necesarios para ejecutar los scripts listado. (A menos que hagan trucos con la carga del módulo que impiden que Module :: ExtractUse los vea.)

9

En el pasado he utilizado Devel::Modlist que es razonablemente buena que le permite ir

perl -d:Modlist script.pl 

Para obtener una lista de los módulos necesarios.

11

Puede utilizar el servicio web en línea en deps.cpantesters.org que le proporcionará muchos datos de dependencia útiles. 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).

3

La forma "obvia", dolorosa pero moderadamente efectiva, es instalar una nueva construcción de base Perl en un lugar apartado (no va a utilizar esto en producción), y luego intentar instalar su 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 doloroso.

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

5

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

Estoy tentado a escribir un script que:

  • búsquedas mi repositorio de control de versiones de los archivos con la extensión .pl o .pm
  • carreras perl -d:Modlist en ellos
  • (gracias!) Vagnerr concatenándolo a la lista de módulos requeridos
  • y finalmente comparándolo con la lista de módulos instalados.

Luego ejecutaba ese script como parte de mi compilación de nivel superior, de modo que cualquier persona que construya algo sabrá si tiene todo lo que necesita para ejecutar cada script de Perl que obtuvieron del control de revisión. Si hay alguna secuencia de comandos perl que nunca se 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 que deje de lado ciertos subdirectorios cuando haces una 'sincronización', tendré que resolverlo para la subversión ...

Sugeriría que el comprobador de dependencias sea una sola secuencia de comandos que busque archivos pl, en lugar de un archivo MAKE individual para comprobar las dependencias para cada script o basado en una lista de nombres de script codificados. Si elige un método que requiere acción del usuario para que se compruebe la existencia de una secuencia de comandos, las personas se olvidarán de realizar esa acción, ya que podrán ejecutar la secuencia de comandos incluso si no realizan la comprobación de dependencia.

Como he dicho, aún no he implementado lo anterior, pero esta pregunta me ha impulsado a intentarlo. Publicaré mi experiencia una vez que haya terminado.

2

Es una respuesta "caballo que está atornillado", 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 e 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 

Pon esto en ~/.cpan/Bundle/(o donde sus vidas .cpan) y luego instalar 'Bundle :: Baz' como un módulo CPAN normal. Esto luego instala todos los módulos listados bajo "= head1 CONTENTS".

3
use Acme::Magic::Pony; 

En serio. Automatizará la instalación de los módulos de Perl si faltan. Consulte la página Acme::Magic::Pony en CPAN.

+0

Interesante, pero si trata de usar que, en un entorno comercial en vivo equipo le operaciones va a ser un poco molesto con usted y quiere para ver si conoce los conceptos de estabilidad y seguridad :-) – Vagnerr

1

Aquí es una función rapidito bash (utilizando 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 
} 
Cuestiones relacionadas