Una forma de comenzar a escribir un módulo es usando la herramienta Perl
h2xs. Supongamos que queremos construir un módulo Parse::Yard
.
La orden es:
$ h2xs -XA -n Parse::Yard Defaulting to backwards compatibility with perl 5.8.4 If you intend this module to be compatible with earlier perl versions, please specify a minimum perl version with the -b option. Writing Parse-Yard/lib/Parse/Yard.pm Writing Parse-Yard/Makefile.PL Writing Parse-Yard/README Writing Parse-Yard/t/Parse-Yard.t Writing Parse-Yard/Changes Writing Parse-Yard/MANIFESTLo cual crea la siguiente estructura de directorios y ficheros:
$ cd Parse-Yard/ Parse-Yard$ tree . |-- Changes |-- MANIFEST |-- Makefile.PL |-- README |-- lib | `-- Parse | `-- Yard.pm `-- t `-- Parse-Yard.t
La herramienta h2xs
fué concebida para ayudar en la transformación
de ficheros de cabecera de C en código Perl. La opción
-X
hace que se omita la creación de subrutinas externas (XS
)
La opción -A
implica que el módulo no hará uso del AutoLoader
.
La opción -n
proporciona el nombre del módulo.
Después de esto tenemos un módulo ''funcional'' que no hace nada. Lo podríamos instalar como si lo hubieramos descargado desde CPAN (para saber más sobre el proceso de instalación, véase 5.14.1).
El programa perl Makefile.PL generado por h2xs se encarga de crear el
fichero Makefile
:
$ cat -n Makefile.PL 1 use 5.008004; 2 use ExtUtils::MakeMaker; 3 # See lib/ExtUtils/MakeMaker.pm for details of how to influence 4 # the contents of the Makefile that is written. 5 WriteMakefile( 6 NAME => 'Parse::Yard', 7 VERSION_FROM => 'lib/Parse/Yard.pm', # finds $VERSION 8 PREREQ_PM => {}, # e.g., Module::Name => 1.1 9 ($] >= 5.005 ? ## Add these new keywords supported since 5.005 10 (ABSTRACT_FROM => 'lib/Parse/Yard.pm', # retrieve abstract from module 11 AUTHOR => 'Lenguajes y Herramientas de Programacion <lhp@ull.es>') : ()), 12 );
El programa usa el módulo ExtUtils::MakeMaker que proporciona
la subrutina WriteMakefile, la cual se encarga de construir el
Makefile
de acuerdo a las especificaciones que se le pasan
como parámetros:
NAME
es el nombre del módulo
VERSION_FROM
dice que fichero contiene
la variable $VERSION
que define la versión de esta
distribución.
PREREQ_PM
es una referencia a un hash
cuyas claves son los nombres de los módulos
de los que depende y los valores son los números de versión
requeridos. Por ejemplo:
PREREQ_PM => { LWP::UserAgent => "1.73", HTTP::Request => "1.27" }
ABSTRACT_FROM
indica el fichero que contiene la descripción, resumen o
abstract del módulo.
ExtUtils::MakeMaker busca en la documentación POD de la distribución
por una línea que case con la expresión regular /^($package\s-\s)(.*)/
.
La costumbre/convenio es que esta sea la primera línea en la sección
=head1 NAME
. El contenido de $2
se interpreta como
abstract.
Por ejemplo en la distribución de Parse::Yapp
podemos ver
que contiene la línea:
nereida:~> sed -ne '/NAME/,/SYNOPSIS/p' `perldoc -l Parse::Yapp` =head1 NAME Parse::Yapp - Perl extension for generating and using LALR parsers. =head1 SYNOPSIS nereida:~> pmdesc Parse::Yapp Parse::Yapp - Perl extension for generating and using LALR parsers.
ABSTRACT
es una línea describiendo el módulo. Se incluye en
el fichero PPD (Perl Package Descriptor). Los ficheros PPD
son ficheros XML.
Por tanto, para crear el Makefile
basta ejecutar
este programa escribiendo perl Makefile.PL
Parse-Yard$ perl Makefile.PL Checking if your kit is complete... Looks good Writing Makefile for Parse::Yard Parse-Yard$ ls -ltr total 44 drwxr-xr-x 2 lhp lhp 4096 2004-12-23 09:47 t -rw-r--r-- 1 lhp lhp 1202 2004-12-23 09:47 README -rw-r--r-- 1 lhp lhp 69 2004-12-23 09:47 MANIFEST -rw-r--r-- 1 lhp lhp 561 2004-12-23 09:47 Makefile.PL drwxr-xr-x 3 lhp lhp 4096 2004-12-23 09:47 lib -rw-r--r-- 1 lhp lhp 158 2004-12-23 09:47 Changes -rw-r--r-- 1 lhp lhp 19549 2004-12-23 16:34 Makefile
En primer lugar se ha comprobado si nuestra aplicación está
completa, para ello WriteMakefile
mira la lista
de ficheros que figura en el fichero MANIFEST
y comprueba
que todos los ficheros en la lista están presentes. Los
contenidos de MANIFEST son:
$ cat MANIFEST Changes Makefile.PL MANIFEST README t/Parse-Yard.t lib/Parse/Yard.pm
Una de las opciones proporcionadas por MakeMaker
es make dist
el cual también usa el fichero MANIFEST
para determinar
que ficheros forman parte de la distribución. Es importante mantener
este fichero actualizado.
MakeMaker
también proporciona un
objetivo MANIFEST
. Tecleando make MANIFEST
se crea
un fichero MANIFEST
que contiene todos los directorios y
subdirectorios del directorio actual. Esta conducta puede
modificarse creando un fichero MANIFEST.SKIP el cual
especifica mediante expresiones regulares
que tipos de ficheros no deben ser incluidos en el
MANIFEST
. Por ejemplo:
$ cat -n /usr/local/src/parrot-0.1.1/MANIFEST.SKIP 1 \.o$ 2 ^\.cvsignore$ 3 /\.cvsignore$ 4 \.cvsignore$ 5 CVS/[^/]+$ 6 ^include/parrot/config\.h$ 7 ^include/parrot/has_header\.h$ 8 ^include/parrot/platform\.h$ 9 ^Makefile$ 10 /Makefile$ 11 ^lib/Parrot/Config\.pm$ 12 ^platform\.c$ ..................
El programa h2xs
creó en lib/Parse/Yapp.pm
un esqueleto inicial del módulo para nosotros.
Estos son sus contenidos:
1 package Parse::Yard; 2 use 5.008004; # Versión mínima de Perl para trabajar 3 use strict; # Por defecto = a la de la instalación 4 use warnings; 5 require Exporter; 6 our @ISA = qw(Exporter); 7 8 # Items to export into callers namespace by default. Note: do not export 9 # names by default without a very good reason. Use EXPORT_OK instead. 10 # Do not simply export all your public functions/methods/constants. 11 12 # This allows declaration use Parse::Yard ':all'; 13 # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK 14 # will save memory. 15 our %EXPORT_TAGS = ( 'all' => [ qw( ) ] ); 16 our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); 17 our @EXPORT = qw( ); 18 our $VERSION = '0.01'; 19 20 # Preloaded methods go here. 21 1; 22 __END__El marcador
__END__
indica el final del código.
El esqueleto construído por h2xs
también contiene
define la estructura de la documentación:
23 # Below is stub documentation for your module. You'd better edit it! 24 25 =head1 NAME 26 27 Parse::Yard - Perl extension for blah blah blah 28 29 =head1 SYNOPSIS 30 31 use Parse::Yard; 32 blah blah blah 33 34 =head1 DESCRIPTION 35 36 Stub documentation for Parse::Yard, created by h2xs. It looks like the 37 author of the extension was negligent enough to leave the stub 38 unedited. 39 40 Blah blah blah. 41 42 =head2 EXPORT 43 44 None by default. 45 46 =head1 SEE ALSO 47 48 Mention other useful documentation such as the documentation of 49 related modules or operating system documentation (such as man pages 50 in UNIX), or any relevant external documentation such as RFCs or 51 standards. 52 53 If you have a mailing list set up for your module, mention it here. 54 55 If you have a web site set up for your module, mention it here. 56 57 =head1 AUTHOR 58 59 Lenguajes y Herramientas de Programacion, E<lt>lhp@E<gt> 60 61 =head1 COPYRIGHT AND LICENSE 62 63 Copyright (C) 2004 by Lenguajes y Herramientas de Programacion 64 65 This library is free software; you can redistribute it and/or modify 66 it under the same terms as Perl itself, either Perl version 5.8.4 or, 67 at your option, any later version of Perl 5 you may have available. 68 69 =cut
Ahora podemos hacer make
:
$ make cp lib/Parse/Yard.pm blib/lib/Parse/Yard.pm Manifying blib/man3/Parse::Yard.3pmComo consecuencia la estructura del proyecto ha cambiado:
Antes de make |
Después de make |
$ cd Parse-Yard/ Parse-Yard$ tree $ tree . |-- Changes |-- MANIFEST |-- Makefile |-- Makefile.PL |-- README |-- lib | `-- Parse | `-- Yard.pm `-- t `-- Parse-Yard.t |
$ tree . |-- Changes |-- MANIFEST |-- Makefile |-- Makefile.PL |-- README |-- blib | |-- arch | | `-- auto | | `-- Parse | | `-- Yard | |-- lib | | |-- Parse | | | `-- Yard.pm | | `-- auto | | `-- Parse | | `-- Yard | `-- man3 | `-- Parse::Yard.3pm |-- lib | `-- Parse | `-- Yard.pm |-- pm_to_blib `-- t `-- Parse-Yard.t |
Este paso cobra importancia cuando el módulo contiene partes escritas en lenguajes externos (por ejemplo en C) y es necesaria la construcción de librerías dinámicas conteniendo código objeto.
Para comprobar que el módulo funciona se hace make test
:
$ make test PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" \ "-e" "test_harness(0, 'blib/lib', 'blib/arch')" t/*.t t/Parse-Yard....ok All tests successful. Files=1, Tests=1, 0 wallclock secs ( 0.04 cusr + 0.01 csys = 0.05 CPU)Una vez escritas las diferentes componentes del módulo, podemos podemos construir una versión para su distribución mediante:
> perl Makefile.PL # Crea el Makefile > make > make dist # o bien: make tardist
La distribución resultante puede ser instalada siguiendo los pasos explicados en la sección 5.14.1.