Perl/Module::Build
Módulo | Module::Build |
---|---|
Versión | Paquete Debian perl-modules version 5.10.1-14 |
Uso | {{{use}}} |
Propósito | Construcción e instalación de librerías Perl |
Sumario
Enlaces y referencias
Conceptos
Introducción
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:
Acción | Descripción |
---|---|
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 directorio lib/. |
docs | Crea la documentación en forma de páginas de manual UNIX y archivos HTML, 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 |
Crea un directorio base para derivar de él el empaquetado final (en formato tarball) que será distribuído como el paquete en sí, ya que serán copiados sobre él los archivos descritos en el manifiesto. El directorio será destruído si ya existe porque es necesario partir de una versión limpia. Dicho directorio obtiene el nombre de la unión del nombre de la distribución (dist_name) y de la versión (dist_version) separados por un guión. |
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 programa Build. |
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 programa test.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:
#!/usr/bin/perl
use Module::Build;
Module::Build->new(
module_name => 'MyIkiWiki::Tools',
license => q(gpl),
dist_version => '0.2',
dist_author => 'Víctor Moral <victor@taquiones.net>',
installdirs => q(vendor),
requires => {
'Perl6::Slurp' => 0,
'List::MoreUtils' => 0,
},
script_files => [
'bin/ikitagit'
],
)->create_build_script();
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.
dist_abstract
Descripción breve del paquete. Generalmente se toma de la sección POD =head1 NAME del módulo del cual se toma la versión.
installdirs
Determina los directorios donde se instalará el software. Acepta como valores site, vendor y core.
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.
Makefile.PL
Para conseguir que el módulo sea compatible con las versiones más antiguas de CPAN o para construir un paquete Debian conviene crear el correspondiente archivo Makefile.PL. El módulo Module::Build::Compat se encarga de construirlo siempre que se encuentre el parámetro create_makefile_pl en el objeto principal.
Los valores que puede tomar este parámetro son:
- small
- El archivo resultante pasa toda la funcionalidad al archivo Build.PL que encuentra en su mismo directorio. Por ello el módulo Module::Build debe estar previamente instalado en el sistema en que se emplee.
- passthrough
- Similar al modo small pero con la diferencia de intentar instalar el paquete Module::Build empleando el programa CPAN si no lo encuentra instalado (preguntando antes al usuario).
- traditional
- Crea un archivo Makefile.PL que asume todo el trabajo desplazando por completo a Build.PL.
- No se recomienda emplear esta opción si se va a preguntar algo al usuario, se necesita obtener algo del entorno del proceso o se pretender derivar algún módulo de Module::Build.
Manifiestos
- Ref: Perl Module Mechanics
- Ref: Perl5 Wiki - CPAN packaging
- Módulos Perl que usan y amplían la información:
Los manifiestos son descripciones del contenido de los paquetes Perl para los que existe un consenso en nomenclatura y manejo.
Los siguientes archivos son significativos para detallar qué se debe empaquetar:
- MANIFEST
- Lista cada uno de los archivos que componen el paquete o librería, a razón de uno por línea, empleando siempre la convención UNIX para describir las rutas.
- Los comentarios comienzan por el carácter almohadilla o por un espacio en blanco hasta el final de cada línea.
... lib/Minero.pm Makefile MANIFEST MANIFEST.SKIP README t/00.load.t t/perlcritic.t t/pod-coverage.t t/pod.t test/direcciones.pl META.yml ...
- MANIFEST.SKIP
- Describe mediante expresiones regulares (una por línea) aquellos archivos y directorios que no deben incluirse en el paquete.
- Se ignoran las líneas que comienzan por una almohadilla (#) o están en blanco.
... .git/ tmp/ _build blib .bak$ .orig$ META.yml Build$ .gz$ -stamp$ .swp$ ...
Recetario
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
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
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:
use lib qw(/usr/share/myprogram/);
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 directorio lib 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ódulo lib 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 que lib/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.