2009-09-12 10 views
5

Tengo un script Perl (foo.pl) que carga Foo.pm desde el mismo directorio utilizando el mecanismo requiere:¿Cómo puedo distribuir mi aplicación Perl como un único archivo?

require "./Foo.pm"; 
... 
my $foo = new Foo::Bar; 

El Foo.pm se adhiere al formato de módulo estándar:

package Foo::Bar; 
... 
1; 

En lugar de distribuir mi aplicación como dos archivos (foo.pl y Foo.pm) me gustaría distribuir solo un archivo. Más específicamente, me gustaría hacer que Foo.pm sea parte del script foo.pl.

¿Cómo lo consigo?

El enfoque trivial de simplemente fusionar los dos archivos (cat foo.pl Foo.pm> foo2.pl) no funciona.

Respuesta

3

Su código no funcionaba (aunque habría sido útil para indicar el mensaje de error (s) que se recibido) porque intentó utilizar Foo :: Bar antes de haber sido definido. Prueba esto:

use strict; 
use warnings; 
my $foo = Foo::Bar->new(); 
# more code... 

# end code 

# begin definitions 
BEGIN { 
    package Foo::Bar; 
    use strict; 
    use warnings; 
    # definitions... 
    1; 

    package Foo::Baz; 
    # more stuff, if you need to define another class 
} 

Adiciones:

2

El esquema general sería reemplazar su "requiere ..." con el contenido de lo que necesita. Hay más que eso (BEGIN {} puede ser necesario), y no estoy exactamente seguro de lo que está involucrado. Seguro, querrías automatizarlo.

Aquí hay una alternativa: generar un único archivo ejecutable en módulos que dependen están envasados ​​dentro de ella usando PAR/pp

+0

Hola wrang-wrang! Gracias por los consejos. Desafortunadamente, la creación de un archivo ejecutable no es una opción, ya que el mismo script se utilizará en múltiples plataformas. – knorv

+1

knorv: si no incluye ningún módulo con un componente compilado XS/C, PAR puede crear archivos .par que sean multiplataforma. Esto NO es un ejecutable binario como con "pp -o foo.exe foo.pl". – tsee

4

Un archivo puede contener múltiples paquetes. Ponga su clase primero, seguido del guión principal:

package Foo::Bar; 

sub new { 
    my $class = shift; 
    return bless {}, $class; 
} 

#... 

package main; 

my $foo = Foo::Bar->new(); 
print ref $foo; # Foo::Bar 
+3

La instrucción 'package' no crea un nuevo ámbito, por lo que puede utilizar' {package Foo :: Bar; REST_OF_THE_CODE} 'para evitar que las cosas se filtren entre los dos paquetes. –

2

Ya tiene unas buenas respuestas. Además, es posible crear un módulo que pueda ejecutarse directamente como un script.

package Foo; 

__PACKAGE__->run(@ARGV) unless caller(); 

sub run { 
    # Do stuff here if you are running the Foo.pm as 
    # a script rather than using it as a module. 
} 

Para detalles adicionales, ver Brian D Foy de How a Script Becomes a Module.

5

Si usted está interesado en el embalaje de su script de Perl en un sistema binario con todos los módulos de los que depende incluido, puede utilizar PAR Packager:

pp -o binary_name foo.pl 
Cuestiones relacionadas