Module::Build
Herramienta estándar para construir e instalar módulos. El proceso generalmente consiste en:
$ perl ./Build.PL
$ ./Build
$ ./Build test
$ ./Build install
Es decir, lo primero que hay que hacer es invocar a Perl con el archivo
Build.PL
-base de todo el proyecto-, y luego usar el programa resultante
para efectuar el resto de las tareas.
Algunas de estas tareas son:
build
Ejecuta las acciones code y docs. Es la acción predeterminada si se llama sin ningún parámetro más.
code
Crea el directorio
blib/
y copia en él todos los archivos.pm
y.pod
que encuentra bajo el directoriolib/
.docs
Crea documentación ([páginas de manual UNIX][1] y archivos HTML, por ejemplo) para todos los elementos instalables que encuentre bajo
blib/
, y contengan documentación POD.distmeta
Actualiza el archivo de descripción del proyecto
META.yml
distsign
Añade una firma criptográfica al paquete.
dist
Crea el paquete para distribución final.
distdir
disttest
Comprueba que la distribución final sea instalable.
clean
Efectúa limpieza en el directorio de los archivos creados durante la la fase anterior (build), pero no borra el directorio
_build/
ni el programaBuild
.distclean
Ejecuta las acciones realclean y la acción distcheck, las cuales sí borran el programa
Build
y el directorio_build
.test
Invoca por orden todos los test regresivos del directorio
t/
ó el programatest.pl
en el directorio raíz del proyecto.fakeinstall
Indica lo que haría la acción install pero sin llevarlo a cabo realmente.
install
Instala los módulos de la librería, la documentación y los scripts en los directorios de instalación. Estos pueden definirse mediante el parámetro
installdirs
.
Algo que conviene advertir es que Module::Build
está diseñado para instalar
módulos y librerías Perl, y no para efectuar operaciones complejas en la
construcción de paquetes (tipo deb y rpm), por lo que querer forzarlo a hacer
otras cosas es fuente de frustación contínua y muchísimos sudores. Sin embargo
no faltan los trucos y recetas para ello, como se puede ver más abajo.
El archivo Build.PL
Este archivo es un programa Perl con instrucciones para crear un programa
Build
que ayude a mantener el paquete. Debe usar el módulo Module::Build
correctamente y es el punto de partida de todo paquete Perl.
Un ejemplo de un archivo podría ser:
1 #!/usr/bin/perl 2 3 use Module::Build; 4 5 Module::Build->new( 6 module_name => 'MyIkiWiki::Tools', 7 license => q(gpl), 8 dist_version => '0.2', 9 dist_author => 'VÃctor Moral <victor@taquiones.net>', 10 installdirs => q(vendor), 11 requires => { 12 'Perl6::Slurp' => 0, 13 'List::MoreUtils' => 0, 14 }, 15 script_files => [ 16 'bin/ikitagit' 17 ], 18 )->create_build_script(); 19
donde se puede ver que todo consiste en crear un objeto Module::Build
e
invocar un método sobre él (create_build_script()
) a fin de crear el otro
ejecutable.
Los parámetros del ejemplo y algunos otros también importantes son:
module_name
Nombre del módulo principal. Es un atajo que abarca los parámetros dist_name y dist_version_from.
dist_name:
Nombre de la distribución tal y como va a empaquetarse.
dist_version_from
Especifica un archivo del cual obtener la versión. Se analiza buscando una línea donde aparezca la variable VERSION y se evalúa como expresión Perl; el resultado será el número de versión.
license
Nombre de la licencia bajo la que se publica el código. Puede elegirse entre bastantes, aunque la más comunes son perl y gpl.
dist_version
Número de versión que abarca todo el paquete.
dist_author
Nombre y dirección de correo del autor de la distribución. Si son varios acepta una referencia a una lista. Si se omite se utiliza la sección POD denominada
=head1 AUTHOR
del módulo del cuál se obtiene la versión.installdirs
Determina los directorios donde se instalará el software. Acepta como valores
site
,vendor
ycore
.requires
Indica qué modulos son necesarios tener instalados para usar éste. Generalmente es un hash cuyas claves son los nombres Perl de los módulos y cuyos valores son la versión mínima exigible. Un valor de cero indica que se acepta cualquier versión de dicho módulo.
script_files
Lista de archivos que serán considerados como ejecutables, e instalados en los directorios adecuados.
Instalando en otros directorios
Supongamos que tenemos una aplicación Perl que contiene un enorme número de módulos (ó tal vez sólo unos pocos), y no queremos que se instalen en los directorios del sistema, junto con los (llamémosles) otros módulos Perl generalistas. ¿ Cómo hacemos ésto ?
Disponemos de varios parámetros con los que podemos jugar:
installdirs
Nos permite elegir entre tres conjuntos de directorios donde instalar componentes:
- core
- site
- vendor
install_path
Sirve para cambiar las rutas de componentes concretos; estos que detallo son los correspondientes al conjunto
vendor
en Debian.- lib:
/usr/share/perl5
- arch:
/usr/lib/perl5
- script:
/usr/bin
- bin:
/usr/bin
- bindoc:
/usr/share/man/man1
- libdoc:
/usr/share/man/man3
- binhtml
- libhtml
- lib:
install_base
Nos permite cambiar con un sólo parámetro el directorio raíz desde el que se forman los demás. Por ejemplo podemos situar todos comenzando por
/home/victor
.destdir
Idóneo para crear paquetes Debian o similares, porque añade un prefijo a todas las rutas, como el de un directorio temporal
/tmp/debian
.
Cualquiera de estos parámetros puede indicarse en la ejecución del programa
Build
ó en el archivo Build.PL
:
$ perl ./Build --destdir=/tmp/debian
$ perl ./Build --install_path lib=/usr/share/mipaquete/
$ perl ./Build --install_base /home/victor
$ perl ./Build --installdirs=core
Preprocesando módulos
Introducción
Lo descrito aquí es una situación real: estamos construyendo una librería para un programa que posteriormente va a ser empaquetado. No queremos que sus módulos, que sólo usa él, vayan en los directorios genéricos del sistema; preferimos utilizar el del propio paquete.
Y es sencillo de conseguir: basta con poner lo siguiente en cada programa que incluya estos módulos:
1 use lib qw(/usr/share/myprogram/); 2 use MyModule;
Para depurar los programas empleamos la siguiente fórmula:
$ perl -Ilib -d myprogram.pl
es decir, anteponemos el directorio lib
del directorio de trabajo en la
lista de directorios dónde localizar módulos. Y funciona estupendamente hasta
que ...
... hasta que creamos un primer paquete de este programa y lo instalamos; luego intentamos algún cambio (de interfaz por ejemplo) e intentamos depurarlo.
Los errores son muy extraños y nada de lo que hagamos en los módulos en desarrollo parece afectar a la depuración del programa. ¿ Qué está ocurriendo ? Pues que no estamos usando la versión de desarrollo en las pruebas, estamos usando la versión instalada en el sistema.
Veamos la secuencia de hechos para un programa (myprogram) que utiliza dos librerías llamadas A y B. Ambas incluyen el párrafo que llama al módulo lib.
- Invocamos el depurador de esta forma: $ perl -Ilib -d myprogram
- Perl inserta al comienzo del array
@INC
el directoriolib
y éste queda de esta forma:lib
/etc/perl
/usr/local/share/perl/5.8.8
/usr/lib/perl5
- Luego busca el primer módulo, el A, que encuentra en
lib/A.pm
, lo lee y lo compila, encontrándose una llamada al módulolib
que introduce cambios en el entorno. Ahora@INC
tiene ya este aspecto:/usr/share/myprogram
lib
/etc/perl
/usr/local/share/perl/5.8.8
/usr/lib/perl5
- Después se le indica que tiene que cargar el módulo B y ... al buscarlo
encuentra primero
/usr/share/myprogram/B.pm
quelib/B.pm
. Y ya está liada :-)
Conclusión: De esto se deduce que no es necesario que los dos módulos modifiquen la ruta de búsqueda de otros módulos para apuntar a la suya propia. Eso debería hacerlo únicamente el programa que les llama.
Pero como un desarrollo grande en Perl puede requerir que varias librerías medio en desarrollo, medio en producción, interaccionen entre sí veamos qué opciones tenemos.