Desarrollando con GNU Autotools (Parte I)

Probablemente muchos desarrolladores habituados a IDEs de hoy día (Eclipse, Visual Studio…) coincidirán conmigo en que la forma de desarrollar utilizando software libre es cuanto menos extraña. Todos conocemos la típica compilación de un paquete de código o tarball en cualquier sistema unix: “./configure & make & make install”. Estos tres comandos parecen mágicamente usables pero a la vez extremadamente complejos en su interior. Los archivos Makefile y configure que vemos en la mayoría de los tarballs de código son habitualmente, cuanto menos, infernales. La razón es que estos archivos no han sido escritos a mano (como antiguamente) sino mediante un proceso automatizado.

Muchos conoceréis autotools, son herramientas de desarrollo mas abstractas que make y configure, finalmente con ellas obtenemos nuestros amados ./configure y Makefile. ¿Pero cuantos habéis desarrollado algo utilizando autotools? Yo no lo había hecho nunca, pero esta tarde me he dispuesto a aprender y hacer algunas pruebas.

¿Para quién está dirigido autotools? Algunas consideraciones previas:
– No es aplicable para el desarrollo en windows si no tienes cygwin.
– Está especialmente para desarrollar en los lenguajes C y C++ aunque en principio es independiente del lenguaje, Mono (la implementación libre de .net) por ejemplo utiliza autotools.
– No apto para la gente que odie montones de archivos autogenerados (aclocal.m4, config.h.in, Makefilem config.status, autom4te.cache , config.sub, stamp-h1,config.guess…)

¿Que herramientas/lenguajes/procesos tienes que controlar para desarrollar minimamente con autotools?

Primero comentar que la suit Autotools está compuesta de dos herramientas principales: Automake y Autoconf. La misión de estas herramientas es autogenerar los mastodónticos archivos de tipo Makefile y configure a partir de otros archivos con un lenguaje de script mas abstracto que tendrán que ser diseñados a mano por nosotros:  Makefile.am y configure.ac. Entonces la respuesta a la pregunta es:

1- Saber construir ficheros “configure.ac” y entender su lenguaje de script. Para tareas básicas es muy fácil y puedes inspirarte en los configure.ac básicos que hay en las referencias.
2- Saber construir ficheros “Makefile.am” y entender su lenguaje de script.

Objetivo: Construir un programa con autotools a partir de un único fichero fuente main.c

1.1 Creando fichero Makefile.am:
En este archivo definiremos qué archivos serán generados a partir de de código fuentes. Se pueden generar varios tipos de archivos resultante típicamente (ejecutable, librería estática, librería dinámica, librería temporal…), para cada uno de ellos se indicará que archivos de código fuente utiliza. También forma parte de sus responsabilidades definir en qué carpeta se instalarán cada uno de los archivos generados

#crearé un ejecutable que se localizará en la carpeta estandar bin. El programa ejecutable se llamará main.
bin_PROGRAMS=main
# El código de main es en main.c
main_SOURCE=main.c

1.2 Creando fichero configure.ac:
Se trata de un script de alto nivel. En él definiremos (entre otras cosas) las dependencias y aplicaciones son necesarias para compilar correctamente este proyecto (Compilador, parseadores, linkadores…)  así como la comprobación de qué librerías y paquetes deben estar instalados en el sistema. También es responsabilidad de este script pedir al usuario todo tipo de parametrizaciones y metainformación para el proceso de construcción (por ejemplo donde desea instalar ciertos componentes o donde se encuentra en el sistema cierta información). Finalmente es el encargado de generar todos los Makefile.in a partir de todos los Makefile.am existentes en la estructura de directorios del proyecto.

#el programa lo llamaré miprograma y su versión será la 0.1
AC_INIT(miprograma,0.1)
#inicializa automake
AM_INIT_AUTOMAKE
#indicamos un requerimiento: programa compilador de C en esta maquina
AC_PROG_CC
#una vez chekeado lo anterior habrá que generar el fichero Makefile a partir de su Makefile.am a partir de su Makefile.in
AC_OUTPUT([Makefile])

1.3 Creando la estructura estandar de directorio raíz de desarrollo

Autotools nos obliga a tener la estrucutra de directorio raíz de desarrollo estándar, esto implica tener que crear una serie de ficheros de información para el usuario (Authors, Readme…). Algunos de ellos pueden ser autogenerados cuando invocamos el comando automake añadiendo el argumento –add-missing, el resto debemos crearlos manualmente.


geus@geuset:~/tutorial$  touch NEWS README AUTHORS ChangeLog
geus@geuset:~/tutorial$  ls
AUTHORS  ChangeLog  configure.ac  main.c  Makefile.am  NEWS  README
geus@geuset:~/tutorial$  aclocal
geus@geuset:~/tutorial$  autoconf
geus@geuset:~/tutorial$  automake --add-missing
configure.ac:2: installing `./install-sh'
configure.ac:2: installing `./missing'
Makefile.am: installing `./INSTALL'
Makefile.am: installing `./COPYING'
Makefile.am: installing `./depcomp'
geus@geuset:~/tutorial$  ls
aclocal.m4      ChangeLog      configure.ac  INSTALL     Makefile     missing
AUTHORS         config.status  COPYING       install-sh  Makefile.am  NEWS
autom4te.cache  configure      depcomp       main.c      Makefile.in  README

Observad que los tres comandos utilizados son típicamente agrupados en un ./autogen.sh. Por otra parte es interesante ver como se ha creado el archivo Makefile.in que será la fuente para la generación del archivo Makefile cuando ejecutemos la configuración del proyecto. Es interesante tener siempre presente quien generó cada archivo ya que un cambio en el origen requerirá una nueva generación del mismo. También encontramos varios archivos temporales que de momento no deberían importarnos.

1.4 Configuración y compilación
Ahora podemos aplicar nuestro clásico ./configure con todas sus opciones estándar.

geus@geuset:~/tutorial$ ./configure --prefix='/opt/prueba'
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... no
checking for mawk... mawk
checking whether make sets $(MAKE)... yes
checking for gcc... gcc
checking for C compiler default output file name... a.out
checking whether the C compiler works... yes
checking whether we are cross compiling... no
checking for suffix of executables...
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking for style of include used by make... GNU
checking dependency style of gcc... gcc3
configure: creating ./config.status
config.status: creating Makefile
config.status: executing depfiles command

En este punto tenemos un archivo Makefile construido que podemos utilizar las reglas típicas: all, clean, install, uninstall… En este caso continuaremos el proceso de construcción estandar.


geus@geuset:~/tutorial$  make
gcc -DPACKAGE_NAME=\"miprograma\" -DPACKAGE_TARNAME=\"miprograma\" -DPACKAGE_VERSION=\"0.1\" -DPACKAGE_STRING=\"miprograma\ 0.1\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE=\"miprograma\" -DVERSION=\"0.1\" -I.     -g -O2 -MT main.o -MD -MP -MF .deps/main.Tpo -c -o main.o main.c
mv -f .deps/main.Tpo .deps/main.Po
gcc  -g -O2   -o main main.o

1.5 Instalación y prueba

geus@geuset:/Datos/Archivos/Proyectos/tutorial$ sudo make install
make[1]: Entering directory `/media/Datos/Archivos/Proyectos/tutorial'
test -z "/opt/prueba/bin" || /bin/mkdir -p "/opt/prueba/bin"
/usr/bin/install -c 'main' '/opt/prueba/bin/main'
make[1]: Nothing to be done for `install-data-am'.
make[1]: Leaving directory `/media/Datos/Archivos/Proyectos/tutorial'
geus@geuset:~/tutorial$ cd /opt/prueba
geus@geuset:/opt/prueba$ ls
bin
geus@geuset:/opt/prueba$ ./bin/main
Hello world
geus@geuset:/opt/prueba$

Resumen
1. Crear archivo configure.ac
2. Crear archivo Makefile.ac
3. Crear archivos de estructura estandar de directorio de desarrollo
4. Ejecutar comandos (aclocal,autoconf,automake)
5. Ejecutar build clásico: ./configure & make & make install

Proximos posts:
– Aplicar el proceso de construcción a todo un proyecto con una estructura recursiva de subdirectorios. Crear librerías estáticas y dinámicas redistribuibles.
– Comprobar paquetes instalados en el sistema durante el proceso de configuración y linkarlos en el proceso de construcción.

Referencias
Estas referencias son interesantes para comenzar desde cero.
http://www.openismus.com/documents/linux/automake/automake.shtml
http://www.delorie.com/gnu/docs/automake/automake_35.html
De esta última es interesante especialmente el chapter 9. Especificando claramente las diferencias para generar un programa ejecutable, una librería distribuible (sea dinámica o estática) y una libreria no distribuible (solo útil en el proceso para ser linkada con otro objeto distribuible)

También muy interesante el libro “Programming with gnu software” (no el de o’really). Nos muestra una visión completa del desarrollo software libre. En concreto los chapters 9, 10, 11 y 12 tratan sobre autotools.
www.lrde.epita.fr/~akim/gnuprog2.pdf

Mas profundidad y como referencia:
http://sources.redhat.com/autobook/autobook/autobook_toc.html#SEC_Contents

2 Responses to Desarrollando con GNU Autotools (Parte I)

  1. matias dice:

    Gracias!!!!!
    No hay mucha informacion al respecto en castellano!-)

    Espero un post sobre traduccion de aplicaciones, y los cambios en el makefile, configure, etc.. Gracias nuevamente..

  2. Pingback: Guía de empaquetamiento con git-buildpackage para Debian GNU/Linux // Hunting Bears

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: