Autotools y amigos

De Wiki GNOME Chile
(Diferencias entre revisiones)
Saltar a: navegación, buscar
m (ProgramacionGTKenC/CapituloVI trasladada a Autotools y amigos: No perteneciente a la programacion de GTK en C)
 
(No se muestran 2 ediciones intermedias realizadas por un usuario)
Línea 1: Línea 1:
 
=Autotools y sus amigos=
 
=Autotools y sus amigos=
  
En esta leccion, aprenderemos a crear y distribuir un proyecto usando las no bien ponderadas Autotools (Autoconf/Automake y amigos).
+
En esta lección, aprenderemos a crear y distribuir un proyecto usando las no bien ponderadas Autotools (Autoconf/Automake y amigos).
  
 
==Comenzando==
 
==Comenzando==
  
Primero, debemos crear un directorio donde ira nuestro proyecto. En mi caso, /home/jci/code/proyecto1
+
Primero, debemos crear un directorio donde irá nuestro proyecto. En mi caso, /home/jci/code/proyecto1
  
 
<pre>$ mkdir ~/code/proyecto1
 
<pre>$ mkdir ~/code/proyecto1
Línea 12: Línea 12:
 
Pueden elegir el directorio que deseen
 
Pueden elegir el directorio que deseen
  
Dentro de ese directorio deben colocar los siguientes archivos:
+
Dentro de ese directorio deben colocar los siguientes archivos (o bien, los encontrar&aacute;n en cualquier proyecto GNU):
  
* AUTHORS, donde iran los autores del programa
+
* AUTHORS, donde van los autores del programa
* LICENSE, donde describiran la licencia que adoptaran para el programa
+
* LICENSE, donde describen la licencia que adoptar&aacute;n para el programa
 
* Changelog, un control de cambios del programa
 
* Changelog, un control de cambios del programa
* COPYING, donde ira una copia de la licencia (en el caso de GPL, GPLv2, etc)
+
* COPYING, donde va una copia de la licencia (en el caso de GPL, GPLv2, etc)
* INSTALL, con instrucciones especiales para la instalacion del programa
+
* INSTALL, con instrucciones especiales para la instalaci&oacute;n del programa
 
* README, con instrucciones acerca del programa, o bien para indicar algo que debe leer el usuario antes de ejecutar el programa
 
* README, con instrucciones acerca del programa, o bien para indicar algo que debe leer el usuario antes de ejecutar el programa
  
Los archivos anteriores no tienen que ver directamente con el sistema de construccion. Estan como manera informativa, indicar la licencia en la cual se distribuyen, entre otros elementos (como dependencias, autores, entre otros topicos).
+
Los archivos anteriores no tienen que ver directamente con el sistema de construcci&oacute;n. Est&aacute;n como manera informativa, indicar la licencia en la cual se distribuyen, entre otros elementos (como dependencias, autores, entre otros t&oacute;picos).
  
Ahora, estos archivos SON requeridos por automake, al momento de construir la distribucion de nuestro proyecto. Lo veremos un poco mas adelante, cuando veamos en profundidad el uso de automake.\
+
Ahora, estos archivos SON requeridos por automake, al momento de construir la distribuci&oacute;n de nuestro proyecto. Lo veremos un poco mas adelante, cuando veamos en profundidad el uso de automake.
  
Recordar que automake es parte de las herramientas de construccion de GNU para distribucion de programas de codigo abierto. Asi que es la razon de por que son necesarios. Aunque hay muchos proyectos que tienen esos mismos archivos en blanco, la regla del dedo gordo es que <b>no usen esos archivos en blanco</b> si quieren distribuir su proyecto con otras personas.
+
Recordar que automake es parte de las herramientas de construcci&oacute;n de GNU para distribuci&oacute;n de programas de codigo abierto. Asi que es la raz&oacute;n de por que son necesarios. Aunque hay muchos proyectos que tienen esos mismos archivos en blanco, la regla del dedo gordo es que <b>no usen esos archivos en blanco, nunca!</b> si quieren distribuir su proyecto con otras personas.
  
 
Empecemos.
 
Empecemos.
Línea 31: Línea 31:
 
==configure.ac==
 
==configure.ac==
  
Esta es la plantilla para el script de configure. Indica, por ejemplo, las dependencias para compilar, tests para ver si existe o no alguna aplicacion o biblioteca del sistema, entre otras.
+
Esta es la plantilla para el script de configure. Indica, por ejemplo, las dependencias para compilar, tests para ver si existe o no alguna aplicaci&oacute;n o biblioteca del sistema, entre otras.
  
Su mision es solamente proveer un unico punto para la configuracion del programa, ademas de hacerlo un poco mas portable. Es la base de la mayoria de las herramientas de construccion de GNU (o en otras partes, encuentran el termino como GNU tools). O bien, de las que se distribuyen como tal.
+
Su misi&oacute;n es solamente proveer un unico punto para la configuraci&oacute;n para la construcci&oacute;n del programa, ademas de hacerlo portable. Es la base de la mayor&iacute;a de las herramientas de construcci&oacute;n de GNU (o en otras partes, encuentran el termino como GNU tools). O bien, de las que se distribuyen como tal.
  
El unico inconveniente de este archivo es que esta escrito en lenguaje de macros, que una vez usando autoconf, seran expandidas a un shell script. Algo complicado al principio de entender.
+
El &uacute;nico inconveniente de este archivo es que esta escrito en lenguaje de macros, que una vez usando autoconf, seran expandidas a un shell script. Algo complicado al principio de entender, pero despues se entiende mucho mejor.
  
 
Ahora, supongamos que mi proyecto se llama "diamante" y que el fuente del programa esta en la ruta src/diamante.c. Haremos un archivo configure.ac para mostrar la forma de crear uno correctamente.
 
Ahora, supongamos que mi proyecto se llama "diamante" y que el fuente del programa esta en la ruta src/diamante.c. Haremos un archivo configure.ac para mostrar la forma de crear uno correctamente.
 +
 +
Este es el contenido de mi <code>configure.ac</code> para el programa "diamante":
  
 
<pre>AC_INIT([Diamante], [0.1], [[email protected]], [diamante])
 
<pre>AC_INIT([Diamante], [0.1], [[email protected]], [diamante])
Línea 75: Línea 77:
 
AC_CONFIG_SRC indica cual es el directorio donde se encuentra el codigo fuente de nuestro programa (en este caso, src/diamante.c).  
 
AC_CONFIG_SRC indica cual es el directorio donde se encuentra el codigo fuente de nuestro programa (en este caso, src/diamante.c).  
  
AC_CONFIG_HEADERS le indica al preprocesador de C que deba leer un archivo antes de compilar. Por lo general, es config.h. Este config.h se crea de forma automatica usando autoheader.  
+
AC_CONFIG_HEADERS le indica al preprocesador de C que deba leer un archivo antes de compilar. Por lo general, es config.h. Este config.h se crea de forma autom&aacute;tica usando autoheader.  
  
 
AM_INIT_AUTOMAKE hace que Automake inicie ;)  
 
AM_INIT_AUTOMAKE hace que Automake inicie ;)  
  
AM_MAINTAINER_MODE hace que se habilite la opcion --enable-maintainer-mode en la configuracion del programa, para agregar opciones tales como bibliotecas con soporte de debugging, entre otras.  
+
AM_MAINTAINER_MODE hace que se habilite la opci&oacute;n --enable-maintainer-mode en la configuracion del programa, para agregar opciones tales como bibliotecas con soporte de debugging, entre otras.  
  
 
AC_PROG_CC y AC_HEADER_STDC le indica a Autoconf que debe aceptar un compilador de C y que debe poseer las cabeceras estandar. Por lo general, si no estan instaladas, el error sera el siguiente
 
AC_PROG_CC y AC_HEADER_STDC le indica a Autoconf que debe aceptar un compilador de C y que debe poseer las cabeceras estandar. Por lo general, si no estan instaladas, el error sera el siguiente
Línea 85: Línea 87:
 
<pre>C compiler error : cannot create executables</pre>
 
<pre>C compiler error : cannot create executables</pre>
  
Autoconf permite el uso de variables. En este caso, cree la variable GTK_MODULES, donde agregue los modulos necesarios para que el programa pudiera compilar. En este caso, gtk+-2.0.
+
Autoconf permite el uso de variables. En este caso, cre&eacute; la variable GTK_MODULES, donde agregu&eacute; los modulos necesarios para que el programa pudiera compilar. En este caso, gtk+-2.0.
  
PKG_CHECK_MODULES permite que pkg-config (importante, lo vimos en la primera leccion) pueda verificar si los modulos existen. Y los comprueba desde la variable GTK_MODULES. Ademas, llena una variable llamada GTK.  
+
PKG_CHECK_MODULES permite que pkg-config (importante, lo vimos en la primera lecci&oacute;n) pueda verificar si los modulos existen. Y los comprueba desde la variable GTK_MODULES. Adem&aacute;s, llena una variable llamada GTK.  
  
La macro AC_SUBST pasa valores desde autoconf a automake (para la creacion del Makefile). Es decir, si existe una cadena para reemplazo (generalmente, $(CADENA) ) en un Makefile.in, configure reemplazara la cadena con el valor que exista en los parentesis de AC_SUBST.
+
La macro AC_SUBST pasa valores desde autoconf a automake (para la creaci&oacute;n del Makefile). Es decir, si existe una cadena para reemplazo (generalmente, $(CADENA) ) en un Makefile.in, configure reemplazar&aacute; la cadena con el valor que exista en los parentesis de AC_SUBST.
  
 
Por ejemplo,  
 
Por ejemplo,  
Línea 99: Línea 101:
 
<pre>-l -g -d --march="i686" </pre>
 
<pre>-l -g -d --march="i686" </pre>
  
Si existe algo asi en el Makefile.in
+
Si existe algo as&iacute; en el Makefile.in
  
 
<pre>CFLAGS=$(CFLAGS)</pre>
 
<pre>CFLAGS=$(CFLAGS)</pre>
  
sera reemplazado asi
+
sera reemplazado as&iacute;
  
 
<pre>CFLAGS=-l -g -d --march="i686"</pre>
 
<pre>CFLAGS=-l -g -d --march="i686"</pre>
  
al crear el archivo Makefile desde la plantilla. Esto se vera mas claro una vez que explique mas adelante el uso de AC_OUTPUT. Asi que sigan leyendo! :D
+
al crear el archivo Makefile desde la plantilla. Esto se ver&aacute; mas claro una vez que explique mas adelante el uso de AC_OUTPUT. Asi que sigan leyendo! :D
  
 
<blockquote>CFLAGS es una variable muy importante al momento de construir cualquier proyecto que requiere el compilador de C (GNU C Compiler, Compilador GNU de C o mas conocido como GCC en este caso particular).
 
<blockquote>CFLAGS es una variable muy importante al momento de construir cualquier proyecto que requiere el compilador de C (GNU C Compiler, Compilador GNU de C o mas conocido como GCC en este caso particular).
  
Esta variable indica que modificadores, opciones, variables o banderas pasar al compilador al momento de construir el proyecto. Algunas veces contiene elementos de optimizacion, otras veces contiene elementos para la depuracion del proyecto, entre otras.
+
Esta variable indica que modificadores, opciones, variables o banderas pasar al compilador al momento de construir el proyecto. Algunas veces contiene elementos de optimizaci&oacute;n, otras veces contiene elementos para la depuraci&oacute;n del proyecto, entre otras.
  
Por ejemplo, la opcion -g indica que el compilador debe agregar opciones para depuracion.  
+
Por ejemplo, la opci&ocute;n -g indica que el compilador debe agregar opciones para depuraci&oacute;n.  
  
 
Si requieren mas info, pueden consultar la pagina de manual de gcc.
 
Si requieren mas info, pueden consultar la pagina de manual de gcc.
Línea 124: Línea 126:
 
./src/diamante.c</pre>
 
./src/diamante.c</pre>
  
Por el momento no me voy a preocupar por los archivos faltantes (NEWS, README, AUTHORS y ChangeLog), ya que no son necesarios para la construccion proyecto por ahora. Pero para distribuir nuestro proyecto, los necesitaremos.  
+
Por el momento no me voy a preocupar por los archivos faltantes (NEWS, README, AUTHORS y ChangeLog), ya que no son necesarios para la construccion del proyecto por ahora. Pero para distribuirlo, los necesitaremos.  
  
 
Ahora, necesito que algunas plantillas (.m4) se copien al directorio de mi proyecto. Lo puedo hacer con aclocal:
 
Ahora, necesito que algunas plantillas (.m4) se copien al directorio de mi proyecto. Lo puedo hacer con aclocal:
Línea 130: Línea 132:
 
<pre>$ aclocal</pre>
 
<pre>$ aclocal</pre>
  
lo que copiara un archivo llamado aclocal.m4
+
lo que copiar&aacute; un archivo llamado aclocal.m4
  
 
Luego, ejecutar autoheader, para que cree automaticamente el archivo config.h.in
 
Luego, ejecutar autoheader, para que cree automaticamente el archivo config.h.in
Línea 140: Línea 142:
 
<pre>$ automake --add-missing --gnu</pre>
 
<pre>$ automake --add-missing --gnu</pre>
  
La salida sera la siguiente:
+
La salida ser&aacute; la siguiente:
  
 
<pre>configure.ac: installing `./install-sh'
 
<pre>configure.ac: installing `./install-sh'
Línea 161: Línea 163:
 
Hmmm...Makefile.in...de donde vendra eso?
 
Hmmm...Makefile.in...de donde vendra eso?
  
Un Makefile en una distribucion con autotools esta creado con una serie de plantillas. Primero Makefile.am para automake que genera un Makefile.in, que es una plantilla para un archivo Makefile.
+
Un Makefile en una distribuci&oacute;n con autotools esta creado con una serie de plantillas. Primero Makefile.am para automake que genera un Makefile.in, que es una plantilla para un archivo Makefile.
  
 
Como no existe el archivo Makefile.in, no puede generar el archivo Makefile.
 
Como no existe el archivo Makefile.in, no puede generar el archivo Makefile.
  
Como se sabe esto?
+
C&oacute;mo se sabe esto?
  
 
Veamos las ultimas lineas del archivo configure.ac:
 
Veamos las ultimas lineas del archivo configure.ac:
Línea 174: Línea 176:
 
])</pre>
 
])</pre>
  
AC_OUTPUT le indica a autoconf que genere esos archivos de forma automagica usando plantillas, o bien archivos .in. En este caso, Makefile.in y src/Makefile.in van a generar los archivos Makefile y src/Makefile, en ese orden. Ninguno de ellos esta. Tampoco podremos crear los archivos a mano, ya que esa es pega de Automake.
+
AC_OUTPUT le indica a autoconf que genere esos archivos de forma autom&aacute;gica usando plantillas, o bien archivos .in. En este caso, Makefile.in y src/Makefile.in van a generar los archivos Makefile y src/Makefile, en ese orden. Ninguno de ellos esta. Tampoco podremos crear los archivos a mano, ya que esa es pega de Automake.
  
 
Creamos entonces un Makefile.am en el directorio raiz:
 
Creamos entonces un Makefile.am en el directorio raiz:
Línea 203: Línea 205:
 
<pre>$ ./configure</pre>
 
<pre>$ ./configure</pre>
  
Esta vez, magicamente, funciono. Sin ningun error. Pero aun falta.  
+
Esta vez, m&aacute;gicamente, funciono. Sin ningun error. Pero aun falta.  
  
Por ahora, configure.ac y configure dejemoslo de lado. Concentremonos en el archivo Makefile.am
+
Por ahora, configure.ac y configure dej&eacute;moslo de lado. Concentr&eacute;monos en el archivo Makefile.am
  
 
==Makefile.am==
 
==Makefile.am==
  
Por el momento el archivo Makefile.am de la raiz del proyecto esta vacio. Pero agreguemos lo siguiente en el:
+
Por el momento el archivo Makefile.am de la raiz del proyecto esta vac&iacute;o. Pero agreguemos lo siguiente en el:
  
 
<pre>SUBDIRS=src</pre>
 
<pre>SUBDIRS=src</pre>
  
La directiva SUBDIRS indica a Automake cuales subdirectorios seguir una vez que termine con el make del directorio raiz. Por ejemplo, si hubiera puesto
+
La directiva SUBDIRS indica a Automake cuales subdirectorios seguir una vez que termine con el make del directorio ra&iacute;z. Por ejemplo, si hubiera puesto
  
 
<pre>SUBDIRS=src po intltool foo bar</pre>
 
<pre>SUBDIRS=src po intltool foo bar</pre>
  
Al ejecutar make, hubiera ejecutado los makefiles de los directorios src, po, intltool, foo y bar, y luego el del raiz. Y en ese orden.
+
Al ejecutar make, hubiera ejecutado los makefiles de los directorios src, po, intltool, foo y bar, y luego el del ra&iacute;z. Y en ese orden.
  
 
Volvamos a ejecutar automake
 
Volvamos a ejecutar automake
Línea 231: Línea 233:
 
<pre>$ make</pre>
 
<pre>$ make</pre>
  
Deberia pasar el proyecto sin ningun problema. Mi salida fue la siguiente:
+
Deber&iacute;a pasar el proyecto sin ningun problema. Mi salida fue la siguiente:
  
 
<pre>$ make
 
<pre>$ make
Línea 246: Línea 248:
 
Perfecto, nuestro sistema esta casi listo.
 
Perfecto, nuestro sistema esta casi listo.
  
Pero solo falta ahora crear un programa, ya que diamante.c esta vacio! Y ademas, poder construirlo.
+
Pero solo falta ahora crear un programa, ya que diamante.c esta vac&iacute;o! Y ademas, poder construirlo para distribuirlo. Es la raz&oacute;n de este cap&iacute;tulo!.
  
Asi que coloquemos un miserable hola mundo de la primera leccion. O bien, el programa que quieran.
+
As&iacute; que coloquemos un miserable <em>hola mundo</em> de la primera lecci&oacute;n. O el programa que quieran.
  
 
Yo voy a ir con este :)
 
Yo voy a ir con este :)
Línea 270: Línea 272:
 
}</pre>
 
}</pre>
  
Ahora, el siguiente actor : src/Makefile.am Ya que Autotools es un sistema de construccion automatica, y hemos dicho en el archivo Makefile.am, de la raiz del proyecto, que uno de los subdirectorios a ejecutar un Makefile es src/, entonces debemos tambien tener una plantilla (src/Makefile.am) para Automake.
+
Ahora, el siguiente actor : src/Makefile.am.
 +
 
 +
Ya que Autotools es un sistema de construcci&oacute;n autom&aacute;tica, y hemos dicho en el archivo Makefile.am, de la raiz del proyecto que uno de los subdirectorios a ejecutar un Makefile es en src/, entonces debemos tambi&eacute;n tener una plantilla (src/Makefile.am) para Automake.
  
 
Agreguemos lo siguiente en src/Makefile.am:
 
Agreguemos lo siguiente en src/Makefile.am:
Línea 280: Línea 284:
 
bin_PROGRAMS = diamante</pre>
 
bin_PROGRAMS = diamante</pre>
  
Recuerdan que AC_SUBST en Autoconf permitia reemplazar cadenas con los valores que tuvieran las variables? Las que se reemplazan son GTK_CFLAGS y GTK_LIBS.
+
Recuerdan que AC_SUBST en Autoconf permit&ia reemplazar cadenas con los valores que tuvieran las variables? Las que se reemplazan son GTK_CFLAGS y GTK_LIBS.
 +
 
 +
La directiva INCLUDES indica que rutas de archivos de cabeceras agregar para compilar efectivamente un programa.  
  
La directiva INCLUDES indica que rutas de archivos de cabeceras agregar para compilar efectivamente un programa. Recuerdan que para compilar un programa en GTK+ era necesario usar el metodo de los backquotes para no colocar una tremenda linea?
+
Recuerdan que para compilar un programa en GTK+ era necesario usar el metodo de los backquotes para no colocar una tremenda linea?
  
 
<pre>$ gcc -o diamante.o diamante `pkg-config --cflags gtk+-2.0`</pre>
 
<pre>$ gcc -o diamante.o diamante `pkg-config --cflags gtk+-2.0`</pre>
  
INCLUDES es equivalente.  
+
INCLUDES es equivalente. Para el caso de pkg-config, es usar el modificador <code>--cflags</code>.
  
Ahora, en INCLUDES hay ademas una variable $top_srcdir. Esa indica el directorio raiz de nuestro proyecto. Es solo en caso que usemos el archivo config.h para algo.  
+
Ahora, en INCLUDES hay ademas una variable $top_srcdir. Esa indica el directorio ra&iacute;z de nuestro proyecto. Es solo en caso que usemos el archivo config.h para algo.  
  
La directiva LIBS es la directiva para enlazar con las bibliotecas necesarias. En los ejemplos anteriores era algo asi
+
La directiva LIBS es la directiva para enlazar con las bibliotecas necesarias. En los ejemplos anteriores era algo as&iacute;
  
 
<pre>$ gcc -o diamante diamante.o `pkg_config --libs gtk+-2.0`</pre>
 
<pre>$ gcc -o diamante diamante.o `pkg_config --libs gtk+-2.0`</pre>
  
En este caso, es equivalente.  
+
En este caso, es equivalente. El modificador --libs para pkg-config es lo mismo.
  
bin_PROGRAMS indica cual es el archivo binario a generar despues que se compilo el archivo. Recordar que se indica cuales archivos compilar en la directiva AC_CONFIG_SRCDIR de Autoconf :-D
+
bin_PROGRAMS indica cual es el archivo binario a generar despues que se compil&oacute; el archivo. Recordar que se indica cuales archivos compilar en la directiva AC_CONFIG_SRCDIR de Autoconf :-D
  
 
De nuevo, ejecutamos automake en la raiz de nuestro proyecto.
 
De nuevo, ejecutamos automake en la raiz de nuestro proyecto.
Línea 306: Línea 312:
 
<pre>$ ./configure</pre>
 
<pre>$ ./configure</pre>
  
Y despues
+
Y despu&eacute;s
  
 
<pre>$ make</pre>
 
<pre>$ make</pre>
  
Y veran que empezara a compilar el fuente que estaba en el directorio src. Excelente!
+
Y veran que empezar&aacute; a compilar el fuente que estaba en el directorio src/. Excelente!
  
 
<pre>$ ls src/
 
<pre>$ ls src/
Línea 319: Línea 325:
 
==Creando la distribucion de nuestro proyecto==
 
==Creando la distribucion de nuestro proyecto==
  
Ahora veamos como podemos distribuirlo para colocar en nuestra pagina web y cachiporrearnos en el asado con los amigos que "publique mi primer programa en GTK+" :) .
+
Ahora veamos como podemos distribuirlo para colocar en nuestra p&aacute;gina web y cachiporrearnos en el asado con los amigos que "publiqu&eacute; mi primer programa en GTK+" :) .
  
Antes de seguir, voy a explicar algunas opciones que son basicas.
+
===make===
 +
 
 +
Antes de seguir, voy a explicar algunas opciones que son b&aacute;sicas.
  
 
Despues de ejecutar
 
Despues de ejecutar
Línea 330: Línea 338:
  
 
<pre>$ make</pre>
 
<pre>$ make</pre>
 
para construirlo.
 
  
 
===make install===
 
===make install===
 +
 +
Pueden ejecutar despues
  
 
<pre>$ make install</pre>
 
<pre>$ make install</pre>
  
(una vez que tengan los privilegios para instalar el programa) para instalarlo de forma que sea para todo el sistema (o bien, que todos los usuarios puedan ejecutar el programa). Requiere privilegios de superusuario.
+
para instalar su proyecto. Por lo general, lo haran en /usr /local /bin, pero solo podr&aacute;n hacerlo si tienen permiso de superusuario en ellos.
 +
 
 +
En algun capitulo a futuro voy a hablar para poder tener un proyecto donde quieran.
  
 
===make clean===
 
===make clean===
 +
 +
Tambi&eacute;n pueden ejecutar
  
 
<pre>$ make clean </pre>
 
<pre>$ make clean </pre>
  
lo que hace es limpiar de los archivos de construccion y archivos resultantes de nuestro proyecto. No borra los Makefiles y podremos ejecutar <code>make</code> cuando queramos.  
+
que lo que hace es limpiar de los archivos de construcci&oacute;n y archivos resultantes de nuestro proyecto. No borra los Makefiles y podremos ejecutar <code>make</code> cuando queramos.  
  
 
En mi caso,  
 
En mi caso,  
Línea 368: Línea 380:
 
<pre>$ make distclean</pre>
 
<pre>$ make distclean</pre>
  
Con make distclean, los archivos que se generan de forma automatica en el sistema de construccion son eliminados, junto con los archivos que se compilan. Asi queda nuestro proyecto sin Makefiles ni archivos de dependencias, corefiles, entre otros.  
+
Con make distclean, los archivos que se generan de forma autom&aacute;tica en el sistema de construcci&oacute;n son eliminados, junto con los archivos que se compilan. Asi queda nuestro proyecto sin Makefiles ni archivos de dependencias, corefiles, entre otros.  
  
 
<pre>$ make distclean
 
<pre>$ make distclean
Línea 390: Línea 402:
  
 
===make distcheck===
 
===make distcheck===
 +
 +
Lo mas importante.
  
 
Va a sonar a chiste, pero hay que ejecutar de nuevo
 
Va a sonar a chiste, pero hay que ejecutar de nuevo
Línea 399: Línea 413:
 
<pre>$ make distcheck</pre>
 
<pre>$ make distcheck</pre>
  
La opcion distcheck realiza una compilacion limpia, copia el arbol de compilacion completo en un directorio y ve si puede construir el proyecto. Si es asi, al final tendremos este lindo mensaje:
+
La opci&oacute;n distcheck realiza una compilaci&oacute;n limpia, copia el arbol de compilaci&oacute;n completo en un directorio y ve si puede construir el proyecto. Si es asi, al final tendremos este lindo mensaje:
  
 
<pre>=============================================
 
<pre>=============================================
Línea 431: Línea 445:
 
diamante-0.1/configure.ac
 
diamante-0.1/configure.ac
 
diamante-0.1/COPYING</pre>
 
diamante-0.1/COPYING</pre>
 +
 +
===Versiones===
  
 
La pregunta mas logica que se deben estar haciendo es "por que supo que era la version 0.1?"
 
La pregunta mas logica que se deben estar haciendo es "por que supo que era la version 0.1?"
Línea 438: Línea 454:
 
<pre>AC_INIT([Diamante], [0.1], [[email protected]], [diamante])</pre>
 
<pre>AC_INIT([Diamante], [0.1], [[email protected]], [diamante])</pre>
  
El segundo parametro es la version de nuestro programa.
+
El segundo par&aacute;metro es la versi&oacute;n de nuestro programa.
  
 
No me creen? Cambien el valor de 0.1 a 0.2. Vuelvan a ejecutar todo en este orden:
 
No me creen? Cambien el valor de 0.1 a 0.2. Vuelvan a ejecutar todo en este orden:

Última revisión de 04:08 8 nov 2008

Contenido

[editar] Autotools y sus amigos

En esta lección, aprenderemos a crear y distribuir un proyecto usando las no bien ponderadas Autotools (Autoconf/Automake y amigos).

[editar] Comenzando

Primero, debemos crear un directorio donde irá nuestro proyecto. En mi caso, /home/jci/code/proyecto1

$ mkdir ~/code/proyecto1
$ cd ~/code/proyecto1

Pueden elegir el directorio que deseen

Dentro de ese directorio deben colocar los siguientes archivos (o bien, los encontrarán en cualquier proyecto GNU):

  • AUTHORS, donde van los autores del programa
  • LICENSE, donde describen la licencia que adoptarán para el programa
  • Changelog, un control de cambios del programa
  • COPYING, donde va una copia de la licencia (en el caso de GPL, GPLv2, etc)
  • INSTALL, con instrucciones especiales para la instalación del programa
  • README, con instrucciones acerca del programa, o bien para indicar algo que debe leer el usuario antes de ejecutar el programa

Los archivos anteriores no tienen que ver directamente con el sistema de construcción. Están como manera informativa, indicar la licencia en la cual se distribuyen, entre otros elementos (como dependencias, autores, entre otros tópicos).

Ahora, estos archivos SON requeridos por automake, al momento de construir la distribución de nuestro proyecto. Lo veremos un poco mas adelante, cuando veamos en profundidad el uso de automake.

Recordar que automake es parte de las herramientas de construcción de GNU para distribución de programas de codigo abierto. Asi que es la razón de por que son necesarios. Aunque hay muchos proyectos que tienen esos mismos archivos en blanco, la regla del dedo gordo es que no usen esos archivos en blanco, nunca! si quieren distribuir su proyecto con otras personas.

Empecemos.

[editar] configure.ac

Esta es la plantilla para el script de configure. Indica, por ejemplo, las dependencias para compilar, tests para ver si existe o no alguna aplicación o biblioteca del sistema, entre otras.

Su misión es solamente proveer un unico punto para la configuración para la construcción del programa, ademas de hacerlo portable. Es la base de la mayoría de las herramientas de construcción de GNU (o en otras partes, encuentran el termino como GNU tools). O bien, de las que se distribuyen como tal.

El único inconveniente de este archivo es que esta escrito en lenguaje de macros, que una vez usando autoconf, seran expandidas a un shell script. Algo complicado al principio de entender, pero despues se entiende mucho mejor.

Ahora, supongamos que mi proyecto se llama "diamante" y que el fuente del programa esta en la ruta src/diamante.c. Haremos un archivo configure.ac para mostrar la forma de crear uno correctamente.

Este es el contenido de mi configure.ac para el programa "diamante":

AC_INIT([Diamante], [0.1], [[email protected]], [diamante])

AC_CONFIG_SRCDIR(src/diamante.c)

AC_CONFIG_HEADER(config.h)

AM_INIT_AUTOMAKE
AM_MAINTAINER_MODE

AC_PROG_CC
AC_HEADER_STDC

AC_SUBST(CFLAGS)
AC_SUBST(CPPFLAGS)
AC_SUBST(LDFLAGS)

GTK_MODULES="gtk+-2.0"
PKG_CHECK_MODULES(GTK, $GTK_MODULES)
AC_SUBST(GTK_CFLAGS)
AC_SUBST(GTK_LIBS)

AC_OUTPUT([
Makefile
src/Makefile
])

Veamos que significa cada cosa.

[editar] Directivas y Variables

AC_INIT indica que Autoconf debe iniciarse para crear el proyecto. Los argumentos son

(nombre_proyecto, version, email, nombrecorto)

AC_CONFIG_SRC indica cual es el directorio donde se encuentra el codigo fuente de nuestro programa (en este caso, src/diamante.c).

AC_CONFIG_HEADERS le indica al preprocesador de C que deba leer un archivo antes de compilar. Por lo general, es config.h. Este config.h se crea de forma automática usando autoheader.

AM_INIT_AUTOMAKE hace que Automake inicie ;)

AM_MAINTAINER_MODE hace que se habilite la opción --enable-maintainer-mode en la configuracion del programa, para agregar opciones tales como bibliotecas con soporte de debugging, entre otras.

AC_PROG_CC y AC_HEADER_STDC le indica a Autoconf que debe aceptar un compilador de C y que debe poseer las cabeceras estandar. Por lo general, si no estan instaladas, el error sera el siguiente

C compiler error : cannot create executables

Autoconf permite el uso de variables. En este caso, creé la variable GTK_MODULES, donde agregué los modulos necesarios para que el programa pudiera compilar. En este caso, gtk+-2.0.

PKG_CHECK_MODULES permite que pkg-config (importante, lo vimos en la primera lección) pueda verificar si los modulos existen. Y los comprueba desde la variable GTK_MODULES. Además, llena una variable llamada GTK.

La macro AC_SUBST pasa valores desde autoconf a automake (para la creación del Makefile). Es decir, si existe una cadena para reemplazo (generalmente, $(CADENA) ) en un Makefile.in, configure reemplazará la cadena con el valor que exista en los parentesis de AC_SUBST.

Por ejemplo,

AC_SUBST(CFLAGS)

CFLAGS es una variable que contiene, por ejemplo, el siguiente valor:

-l -g -d --march="i686" 

Si existe algo así en el Makefile.in

CFLAGS=$(CFLAGS)

sera reemplazado así

CFLAGS=-l -g -d --march="i686"

al crear el archivo Makefile desde la plantilla. Esto se verá mas claro una vez que explique mas adelante el uso de AC_OUTPUT. Asi que sigan leyendo! :D

CFLAGS es una variable muy importante al momento de construir cualquier proyecto que requiere el compilador de C (GNU C Compiler, Compilador GNU de C o mas conocido como GCC en este caso particular). Esta variable indica que modificadores, opciones, variables o banderas pasar al compilador al momento de construir el proyecto. Algunas veces contiene elementos de optimización, otras veces contiene elementos para la depuración del proyecto, entre otras. Por ejemplo, la opci&ocute;n -g indica que el compilador debe agregar opciones para depuración. Si requieren mas info, pueden consultar la pagina de manual de gcc.

Hasta el momento, tengo creado un directorio con los siguientes archivos:

./configure.ac
./src
./src/diamante.c

Por el momento no me voy a preocupar por los archivos faltantes (NEWS, README, AUTHORS y ChangeLog), ya que no son necesarios para la construccion del proyecto por ahora. Pero para distribuirlo, los necesitaremos.

Ahora, necesito que algunas plantillas (.m4) se copien al directorio de mi proyecto. Lo puedo hacer con aclocal:

$ aclocal

lo que copiará un archivo llamado aclocal.m4

Luego, ejecutar autoheader, para que cree automaticamente el archivo config.h.in

$ autoheader

Ahora, ejecutar

$ automake --add-missing --gnu

La salida será la siguiente:

configure.ac: installing `./install-sh'
configure.ac: installing `./mkinstalldirs'
configure.ac: installing `./missing'

Ahora, ejecutemos autoconf

$ autoconf

Y listo. Tendremos un configure limpiecito.

ALTO! Veamos que pasa al ejecutar ./configure

$ ./configure
[...challa...]
configure: creating ./config.status
config.status: error: cannot find input file: Makefile.in

Hmmm...Makefile.in...de donde vendra eso?

Un Makefile en una distribución con autotools esta creado con una serie de plantillas. Primero Makefile.am para automake que genera un Makefile.in, que es una plantilla para un archivo Makefile.

Como no existe el archivo Makefile.in, no puede generar el archivo Makefile.

Cómo se sabe esto?

Veamos las ultimas lineas del archivo configure.ac:

AC_OUTPUT([
Makefile
src/Makefile
])

AC_OUTPUT le indica a autoconf que genere esos archivos de forma automágica usando plantillas, o bien archivos .in. En este caso, Makefile.in y src/Makefile.in van a generar los archivos Makefile y src/Makefile, en ese orden. Ninguno de ellos esta. Tampoco podremos crear los archivos a mano, ya que esa es pega de Automake.

Creamos entonces un Makefile.am en el directorio raiz:

$ touch Makefile.am

y volvemos a ejecutar

$ automake --gnu --add-missing

La salida es un poco mas larga que la vez anterior:

Makefile.am: installing `./COPYING'
Makefile.am: installing `./INSTALL'
Makefile.am: required file `./NEWS' not found
Makefile.am: required file `./README' not found
Makefile.am: required file `./AUTHORS' not found
Makefile.am: required file `./ChangeLog' not found

Me indica que los archivos NEWS, README, AUTHORS y ChangeLog no existen. Creemos estos archivos en blanco:

$ touch NEWS README AUTHORS ChangeLog

No es necesario volver a ejecutar automake, ya que no hemos modificado Makefile.am

Ahora, un configure nuevamente:

$ ./configure

Esta vez, mágicamente, funciono. Sin ningun error. Pero aun falta.

Por ahora, configure.ac y configure dejémoslo de lado. Concentrémonos en el archivo Makefile.am

[editar] Makefile.am

Por el momento el archivo Makefile.am de la raiz del proyecto esta vacío. Pero agreguemos lo siguiente en el:

SUBDIRS=src

La directiva SUBDIRS indica a Automake cuales subdirectorios seguir una vez que termine con el make del directorio raíz. Por ejemplo, si hubiera puesto

SUBDIRS=src po intltool foo bar

Al ejecutar make, hubiera ejecutado los makefiles de los directorios src, po, intltool, foo y bar, y luego el del raíz. Y en ese orden.

Volvamos a ejecutar automake

$ automake --gnu --add-missing

Y ahora

$ ./configure

Si todo va bien, ejecutemos

$ make

Debería pasar el proyecto sin ningun problema. Mi salida fue la siguiente:

$ make
make  all-recursive
make[1]: Entering directory `/home/jci/code/diamante'
Making all in src
make[2]: Entering directory `/home/jci/code/diamante/src'
make[2]: Nothing to be done for `all'.
make[2]: Leaving directory `/home/jci/code/diamante/src'
make[2]: Entering directory `/home/jci/code/diamante'
make[2]: Leaving directory `/home/jci/code/diamante'
make[1]: Leaving directory `/home/jci/code/diamante'

Perfecto, nuestro sistema esta casi listo.

Pero solo falta ahora crear un programa, ya que diamante.c esta vacío! Y ademas, poder construirlo para distribuirlo. Es la razón de este capítulo!.

Así que coloquemos un miserable hola mundo de la primera lección. O el programa que quieran.

Yo voy a ir con este :)

#include <gtk/gtk.h>

int main(int argc, char * argv[])
{
	GtkWidget * ventana;
	GtkWidget * boton;

	gtk_init(&argc, &argv);
	
	ventana = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	boton = gtk_button_new_with_label("Hola Mundo");
	
	gtk_container_add(GTK_CONTAINER(ventana), boton);
	gtk_widget_show_all(ventana);

	gtk_main();
}

Ahora, el siguiente actor : src/Makefile.am.

Ya que Autotools es un sistema de construcción automática, y hemos dicho en el archivo Makefile.am, de la raiz del proyecto que uno de los subdirectorios a ejecutar un Makefile es en src/, entonces debemos también tener una plantilla (src/Makefile.am) para Automake.

Agreguemos lo siguiente en src/Makefile.am:

INCLUDES = -I$(top_srcdir) $(GTK_CFLAGS)

LIBS = $(GTK_LIBS)

bin_PROGRAMS = diamante

Recuerdan que AC_SUBST en Autoconf permit&ia reemplazar cadenas con los valores que tuvieran las variables? Las que se reemplazan son GTK_CFLAGS y GTK_LIBS.

La directiva INCLUDES indica que rutas de archivos de cabeceras agregar para compilar efectivamente un programa.

Recuerdan que para compilar un programa en GTK+ era necesario usar el metodo de los backquotes para no colocar una tremenda linea?

$ gcc -o diamante.o diamante `pkg-config --cflags gtk+-2.0`

INCLUDES es equivalente. Para el caso de pkg-config, es usar el modificador --cflags.

Ahora, en INCLUDES hay ademas una variable $top_srcdir. Esa indica el directorio raíz de nuestro proyecto. Es solo en caso que usemos el archivo config.h para algo.

La directiva LIBS es la directiva para enlazar con las bibliotecas necesarias. En los ejemplos anteriores era algo así

$ gcc -o diamante diamante.o `pkg_config --libs gtk+-2.0`

En este caso, es equivalente. El modificador --libs para pkg-config es lo mismo.

bin_PROGRAMS indica cual es el archivo binario a generar despues que se compiló el archivo. Recordar que se indica cuales archivos compilar en la directiva AC_CONFIG_SRCDIR de Autoconf :-D

De nuevo, ejecutamos automake en la raiz de nuestro proyecto.

$ automake --gnu --add-missing

Luego

$ ./configure

Y después

$ make

Y veran que empezará a compilar el fuente que estaba en el directorio src/. Excelente!

$ ls src/
diamante  diamante.c  diamante.o  Makefile  Makefile.am  Makefile.in

Perfecto! Es justo lo que necesito. Y hemos generado nuestro primer proyecto con Autotools!

[editar] Creando la distribucion de nuestro proyecto

Ahora veamos como podemos distribuirlo para colocar en nuestra página web y cachiporrearnos en el asado con los amigos que "publiqué mi primer programa en GTK+" :) .

[editar] make

Antes de seguir, voy a explicar algunas opciones que son básicas.

Despues de ejecutar

$ ./configure

Pueden construir el proyecto con

$ make

[editar] make install

Pueden ejecutar despues

$ make install

para instalar su proyecto. Por lo general, lo haran en /usr /local /bin, pero solo podrán hacerlo si tienen permiso de superusuario en ellos.

En algun capitulo a futuro voy a hablar para poder tener un proyecto donde quieran.

[editar] make clean

También pueden ejecutar

$ make clean 

que lo que hace es limpiar de los archivos de construcción y archivos resultantes de nuestro proyecto. No borra los Makefiles y podremos ejecutar make cuando queramos.

En mi caso,

$ make clean

dio el siguiente resultado:

$ make clean
Making clean in src
make[1]: Entering directory `/home/jci/code/diamante/src'
test -z "diamante" || rm -f diamante
rm -f *.o core *.core
make[1]: Leaving directory `/home/jci/code/diamante/src'
Making clean in .
make[1]: Entering directory `/home/jci/code/diamante'
make[1]: Nothing to be done for `clean-am'.
make[1]: Leaving directory `/home/jci/code/diamante'

[editar] make distclean

Lo interesante viene si quieren distribuir su proyecto. Para eso pueden usar

$ make distclean

Con make distclean, los archivos que se generan de forma automática en el sistema de construcción son eliminados, junto con los archivos que se compilan. Asi queda nuestro proyecto sin Makefiles ni archivos de dependencias, corefiles, entre otros.

$ make distclean
make[1]: Entering directory `/home/jci/code/diamante/src'
test -z "diamante" || rm -f diamante
rm -f *.o core *.core
rm -f *.tab.c
rm -f 
rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
rm -rf ./.deps
rm -f Makefile
make[1]: Leaving directory `/home/jci/code/diamante/src'
Making distclean in .
make[1]: Entering directory `/home/jci/code/diamante'
rm -f 
rm -f config.h stamp-h1
rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
make[1]: Leaving directory `/home/jci/code/diamante'
rm -f config.status config.cache config.log configure.lineno
rm -f Makefile

[editar] make distcheck

Lo mas importante.

Va a sonar a chiste, pero hay que ejecutar de nuevo

$ ./configure

Y una vez que termine, ejecutar

$ make distcheck

La opción distcheck realiza una compilación limpia, copia el arbol de compilación completo en un directorio y ve si puede construir el proyecto. Si es asi, al final tendremos este lindo mensaje:

=============================================
diamante-0.1.tar.gz is ready for distribution
=============================================

Ese archivo .tar.gz podremos pasarlo a nuestros amigos, o bien respaldar donde queramos. :D

Veamos que tiene dentro...

$ tar tfz diamante-0.1.tar.gz
diamante-0.1/
diamante-0.1/aclocal.m4
diamante-0.1/AUTHORS
diamante-0.1/Makefile.am
diamante-0.1/README
diamante-0.1/install-sh
diamante-0.1/depcomp
diamante-0.1/config.h.in
diamante-0.1/INSTALL
diamante-0.1/ChangeLog
diamante-0.1/configure
diamante-0.1/src/
diamante-0.1/src/Makefile.am
diamante-0.1/src/diamante.c
diamante-0.1/src/Makefile.in
diamante-0.1/missing
diamante-0.1/Makefile.in
diamante-0.1/NEWS
diamante-0.1/mkinstalldirs
diamante-0.1/configure.ac
diamante-0.1/COPYING

[editar] Versiones

La pregunta mas logica que se deben estar haciendo es "por que supo que era la version 0.1?"

Recuerdan la primera linea de AC_INIT del archivo configure.ac?

AC_INIT([Diamante], [0.1], [[email protected]], [diamante])

El segundo parámetro es la versión de nuestro programa.

No me creen? Cambien el valor de 0.1 a 0.2. Vuelvan a ejecutar todo en este orden:

$ autoheader
$ autoconf
$ automake --gnu --add-missing
$ make distclean
$ ./configure
$ make distcheck
...[challa]...

=============================================
diamante-0.2.tar.gz is ready for distribution
=============================================

Bonito, no?

Herramientas personales
Espacios de nombres

Variantes
Acciones
Navegación
Herramientas