Las herramientas a través de un ejemplo

A continuación se explica el funcionamiento de las herramientas de autoconfiguración de proyectos de desarrollo a través del proyecto "hola-mundo", que consistirá en armar el proyecto para una aplicación muy sencilla que sirva para mostrar la integración de las herramientas y finalizar con el paquete a distribuir a la comunidad.

Las herramientas funcionan en torno a los archivos configure.in y Makefile.am, y es su definición la que guiará el funcionamiento de cada uno de los programas de automatización. Lo importante, en un principio, es conocer como construir el archivo configure.in y cómo actúan los programas en todo a este archivo.

La secuencia de construcción consiste de los siguientes comandos: aclocal, autoheader, autoconf y automake, lo que finalmente termina generando el script configure y varios plantillas con extensión .in (Makefile.in entre los más importantes).

aclocal

automake, que es la última utilidad en ser invocada, provee macros para autoconf, programa que necesita conocer de su existencia. Para ello, se define como interfaz el archivo aclocal.m4, que será empleado por autoconf para buscar macros de automake.

aclocal es una utilidad que permite generar automáticamente el archivo aclocal.m4. aclocal busca macros en todos los archivos .m4 del directorio en donde se ejecuta y finalmente busca en el archivo configure.in. Todas esas macros se incluirán en el archivo aclocal.m4, así como todas las macros de las cuales dependen. De esta forma, se puede emplear el mismo archivo configure.in para el uso de autoconf y automake simultáneamente.

Para facilitar las personalización en proyectos que requieran macros propias, se ha definido el archivo acinclude.m4. Las macros allí definidas, pueden ser empleadas también en el archivo configure.in.

El archivo aclocal.m4 solo será generado si se encuentran macros de automake, es decir, aquellas que comiencen con el prefijo AM_.

Por ejemplo, un archivo configure.in básico (sin funcionalidad):

Ejemplo 1. configure.in básico (sin funcionalidad)

	AC_PREREQ(2.52)
	AC_INIT(hola-mundo,0.1)

	AM_AUTOMAKE_VERSION(1.7.2)

	AC_OUTPUT(Makefile)
	

Después de ejecutar aclocal, se creará el archivo aclocal.m4 bastante pequeño cuya macro, AM_AUTOMAKE_VERSION, sirve para indicar que se requiere la versión 1.7 de la API de automake a utilizar. En este ejemplo, se ha empleado para ilustrar el archivo aclocal.m4 generado.

Sin embargo, con en el ejemplo anterior no es posible utilizar automake, puesto que no se encuentran disponibles todas las macros que automake requiere. Para ello es necesaria la macro AM_INIT_AUTOMAKE[1], que debe ser la primera macro de automake en ser invocada.

Una disgresión entre AC_INIT y AM_INIT_AUTOMAKE. Ambas macros son capaces de inicializar el nombre del paquete y la versión (que más adelante se empleará).

La forma antigua de hacerlo es:

Ejemplo 2. Método antiguo

	AC_INIT
	AM_INIT_AUTOMAKE(programa,version)
	

La forma nueva de hacerlo es:

Ejemplo 3. Método nuevo

	AC_INIT(programa,version)
	AM_INIT_AUTOMAKE
	

Actualmente AM_INIT_AUTOMAKE acepta el nombre del paquete y la versión, pero no hay garantía que en el futuro siga funcionando de esa forma. Por lo tanto, es conveniente usar el nuevo formato.

autoheader

autoheader crea una plantilla con un conjunto de directivas #define que pueden emplearse desde los programas en C. Para indicar el nombre del archivo se debe emplear la macro AC_CONFIG_HEADERS. En versiones antiguas[2], se empleaba AM_CONFIG_HEADER, la cual está obsoleta.

El archivo configure.in quedará entonces:

Ejemplo 4. configure.in básico

	AC_PREREQ(2.52)
	AC_INIT(hola-mundo,0.1)

	AC_CONFIG_HEADERS(config.h)

	AM_AUTOMAKE_VERSION(1.7)
	AM_INIT_AUTOMAKE

	AC_PROG_CC

	AC_OUTPUT([
	  Makefile
	  src/Makefile
	])
	

autoheader creará el archivo config.h.in, una plantilla que en un proceso posterior pasará a ser config.h El nombre del archivo es arbitrario, pero config.h ya es estándar en las aplicaciones. Dicho archivo puede emplearse en los programas a través de la directiva \lstinline[language=C,frame={tb}]{#include <config.h>}.

Por lo tanto, la secuencia de ejecución será:

Ejemplo 5.

	$ aclocal
	$ autoheader
	$ autoconf
	

En este instante se han creado los archivos aclocal.m4, config.h.in y autom4te.cache. Los dos últimos, generados por autoheader. El resultado en config.h.in es el siguiente:

Ejemplo 6.

	/* config.h.in.  Generated from configure.in by autoheader.  */

	/* Name of package */
	#undef PACKAGE

	/* Define to the address where bug reports for this package should be sent. */
	#undef PACKAGE_BUGREPORT

	/* Define to the full name of this package. */
	#undef PACKAGE_NAME

	/* Define to the full name and version of this package. */
	#undef PACKAGE_STRING

	/* Define to the one symbol short name of this package. */
	#undef PACKAGE_TARNAME

	/* Define to the version of this package. */
	#undef PACKAGE_VERSION

	/* Version number of package */
	#undef VERSION
	

Como se puede apreciar, es una plantilla, donde cada directiva \lstinline[language=C]{#undef} será reemplazada por los valores reales y cuyos valores serán obtenidos durante la ejecución del script configure, más adelante. De esta manera, se define en un solo lugar el nombre de la aplicación y su versión, facilitando la mantención y la liberación de nuevas versiones.

autoconf

autoconf es una herramientas que permite construir paquetes de programas de una manera más portable. Provee una seria de pruebas que se realizan en el sistema donde se instalará para determinar sus características antes de ser compilado, de tal forma que el código fuente de un programa puede adaptarse en mejor manera a los diferentes sistemas.

autoconf permite generar un script, llamado configure, que es el encargado de realizar las comprobaciones para determinar la disponibilidad y ubicación de todos los requisitos para la construcción exitosa de un programa. Cuando se encuentra bien construidos, permite instalar y desinstalar muy fácilmente las aplicaciones.

autoconf genera un script a partir de de las definiciones en configure.in, y sus macros se reconocen por el uso del prefijo AC_.

autoconf primero busca en las macros que tiene en forma predefinida y luego en el archivo aclocal.m4, si es que existe[3].

En estos momentos se pueden detallar las macros no explicadas del programa \ref{configure.in-basico}:

  • AC_PREREQ, indica que la versión de autoconf requerida debe ser igual o mayor a 2.52:

  • AC_INIT, es la macro encargada de inicializar las funcionalidades de autoconf. Recibe como parámetros el nombre de la aplicación y su respectiva versión. Cada que se libere una nueva versión, se debe incrementar el segundo parámetro, para indicar la nueva versión en desarrollo.

  • AC_PROG_CC indica que se trata de programas en C y que se requiere de compilador y las bibliotecas básicas de desarrollo.

  • AC_OUTPUT indica los archivos que finalmente deben ser generados por el script configure.

automake

automake es una herramienta que permite generar en forma automática archivos Makefile, de acuerdo a un conjunto de estándares, simplificando el proceso de organización de las distinas reglas así como proveyendo funciones adicionales que permiten un mejor control sobre los programas.

libtoolLibtool es una interfaz entre el compilador y el enlazador para facilitar la generación de bibliotecas estáticas y dinámicas de una forma más portable, independiente de la plataforma en la cual se encuentran ejecutándose.

La utilidad make es ampliamente usada en el desarrollo de aplicaciones, ya que a partir de un archivo, llamado Makefile, que contiene reglas de dependencia es capaz de determinar las acciones a seguir, comúnmente determinar que programas deben compilarse para obtener la aplicación.

Sin embargo, es tedioso crear las reglas para que construya a través de varios subdirectorios, con seguimiento automático de dependencias. Si se trabaja en varios proyectos, prácticamente significa reinventar la rueda en cada uno de ellos, sin mecionar los problemas de portabilidad.

automake permite automatizar esta labor, para ello emplea un archivo Makefile.am como fuente, en donde se indica lo esencial a construir, y será necesario por cada uno de los directorios en que se necesite realizar alguna tarea. A partir de ello, generará una plantilla llamada Makefile.in, la que finalmente se traducirá en Makefile cuando se ejecute el script configure.

Los archivos Makefile.in que se generarán dependerán exclusivamente de lo que se indique en la macro AC_OUTPUT.

automake puede proveer los archivos que son estándares (ver la sección ) en cada aplicación, y salvo que se desee realizar algún cambio, es posible trabajar transparentemente con lo que sugiera, para ello basta usar la opción '--add-mising' de automake. Esto creará enlaces simbólicos de los archivos, para realizar una copia es necesario añadir la opción '--copy'. Es importante revisar el archivo COPYING, puesto que contiene la licecia de uso de la aplicación. Por omisión, será GPL.

El archivo Makefile.am del directorio raíz contendrá:

Ejemplo 7. Makefile.am del proyecto 'hola mundo'

	

En donde se indica, que debe procesar el subdirectorio src. SUBDIRS es una variable genérica, en donde se especifican todos los subdirectorios que se deben procesar. De cierta forma, se indican los directorios en que hay dependencias que se deben satisfacer. Cuando se ejecute la utilidad make, ingresará primero a cada uno de los subdirectorios y así sucesivamente.

Luego, se indican todos los archivos que son parte extra de la aplicación y que se desean distribuir, además de la aplicación ejecutable.

Dentro del directorio src, también se encuentra un archivo Makefile. En este directorio se encuentra el programa propiamente tal, por lo tanto las reglas son distintas.

Ejemplo 8. src/Makefile.am del proyecto 'hola mundo'

	

La variable bin_PROGRAMS indica como se llamará la aplicación final, el archivo binario (ejecutable). Si se desea generar una biblioteca y no un programa ejecutable, se debe emplear libexec_PROGRAMS.

Cabe notar que ha sido llamado 'hola-mundo'. Ese mismo texto se empleará como prefijo para otras reglas, tales como: hola_mundo_SOURCES[4], hola_mundo_LDADD, por nombrar las más comunes.

El programa

Como se trata de una aplicación de ejemplo, el programa "hola-mundo", imprimirá el nombre de la aplicación, su versión y el clásico "hola mundo". El nombre de la aplicación y versión se obtienen de las definiciones de la macro AC_INIT en el archivo configure.in y utilizados a través del archivo config.h.

Ejemplo 9. Programa hola-mundo.c

	

Finalizando la configuración

En este punto, ya se encuentran todos los archivos preparados para ejecutar el script configure. Hay que notar que, al momento de distribuir la aplicación, no es necesario que la contraparte disponga de aclocal, autoheader, autoconf y automake; el script contiene toda la información necesaria para realizar las verificaciones en forma autónoma.

Ya se encuentra todo preparado y resumiendo, la ejecución completa debiera ser:

Ejemplo 10.

	

Ya se encuentra nuestro programa compilado y funcionando. Si se desea distribuirlo, basta ejecutar:

Ejemplo 11.

	

De esta forma, se ha obtenido la aplicación empaquetada en un archivo listo para ser liberado como la versión 0.1 de hola-mundo.

Entre las reglas mas comunes se encuentran: make install, make uninstall, make clean, make distclean.



[1] La excepción la constituye AM_AUTOMAKE_VERSION.

[2] Es conveniente verificar la versión de automake que se emplea para desarrollar. La versión 1.4 requiere de AM_CONFIG_HEADER. La versión en uso actual (1.7.6) acepta ambas, aunque recomienda AC_CONFIG_HEADERS.

[3] Recordar que aclocal.m4 se genera previamente con aclocal.

[4] Notar que se reemplazó el símbolo '-' por '_' en el nombre de la regla.