Mostrando entradas con la etiqueta autotools. Mostrar todas las entradas
Mostrando entradas con la etiqueta autotools. Mostrar todas las entradas

miércoles, 20 de noviembre de 2013

Autotools (3): Integración de libtool en autotools para la creación de una biblioteca a instalar en el sistema.

En otros post anteriores vimos la escencia de las bibliotecas así como de libtool, si además haz realizado aunque sea un “hello world” con autotools entonces ahora veamos como integramos a libtool con autotool para la creación de una biblioteca.

#configure.ac
LT_INIT: Es la forma en que actualmente se define LIBTOOL.

# Checks for programs.
AC_PROG_CXX: Chequea por un compilador para c++.
AC_PROG_AWK: Chequea gawk, mawk, nawk, and awk, en ese orden y lo establece como variable.
AC_PROG_CC: Chequea por un compilador para c.
AC_PROG_CPP: Muetra el valor de la variable CPP que contiene el preprocesador.
AC_PROG_INSTALL: Muetra el valor de la variable INSTALL para instalación.
AC_PROG_LN_S: Chequea que ls sistema en que te encuentras soporta links simbólicos(ln -s), en caso que este no esté disponible lo establece a ln, en otro caso a cp -pR.
AC_PROG_MAKE_SET: Establece el comando make.

#lib/Makefile.am:
CLEANFILES: Para que make clean borre los archivos que coincidan.

AM_CPPFLAGS: El contenido de esta variable es pasado a todas las reglas de compilación que invoquen el preprocesador de C.

Definiciones para el uso de pkg-config una vez creada la lib.
pkgconfigdir = @libdir@/pkgconfig
pkgconfig_DATA = libmatX.pc

A diferencia del primer ejemplo donde poniamos bin_PROGRMAS para crear ejecutables aquí usamos esta macro a la cual le decimo el nombre de la lib a crear y en el source debe transformar el nombre a su forma canónica.
lib_LTLIBRARIES = libmatX.la
libmatX_la_SOURCES = \
matX.cc

libmatX_la_LDFLAGS: Flags para el elnlazador.


“#Headers/Makefie.am
includedir: Referencia al directorio include donde se pondran los headers
nobase_include_HEADERS: Para que no se instale dos veces con una invocación del programa.
Una vez configurado el proyecto procedemos a la contrucción:
1. mkdir -p m4
2. libtoolize --copy –force
3. aclocal -I m4
4. autoheader
5. autoconf
6. automake -a
7. ./configure
.8 make
Ya podrás ver que se ha creado lib/libmatX.la, incluso lo podrías leer(cat lib/libmatX.la) ya que es texto plano, en este punto la biblioteca ya es usable, esto sería en nuestro progrma usar la macro LDADD (tambien con el nombre del ejecutable como prefijo y con _ al final) para esto puedes consultar GNU Automake aunque este ejemplo cuneta con su *.pc.
9. sudo make install
Ya deberías poder verificar como instalada la biblioteca en tu sistema
10. pkg-config --list-all | grep hello_libtool

Ya teniendo esta infraestructura básica del proyecto veamos como crear las bibliotecas estática y dinámica correspondiente.

Biblioteca estática:
make clean
./configure --disable-shared
make
Biblioteca dinámica:
make clean
./configure --disable-static
make

NOTA: En caso de no especificar se crea la dinámica y la estática.

Desde aquí puedes descargar el ejemplo:

git clone https://github.com/denisacostaq/EmbeLinux --branch hello-libtool

sábado, 21 de septiembre de 2013

Autotools(2): Integracíon de getttext con autotools para internacionalizar aplicaciones (intltool).

Cuando deceamos que nuestra aplicación esté disponible bajo varios idiomas tenemos varias opciones, una de ellas es el conjunto de funciones gettext (glibc-reference-manual). En este pos veremos como inttool se integra de manera natural a autotools(see Autotools(1))., gettext es quien extrae las cadenas para su traducción pero inttool extiende sus funcionalidades permitiendo:
  • -Detectar las herramientas necesarias para la configuración y contrucción del proyecto.
  • -Extraer las cadenas a traducir.
  • -Mezclar las cadenas en la app final.


A partir de este punto nos basaremos en nuesto “hola mundo” inicial (git clone https://github.com/denisacostaq/EmbeLinux --branch hola-mundo, puedes probar ahora ejecutar autoscan en el directorio del proyecto y después cat configure.scan :) ), agregaremos el directorio po en la raiz de nustro proyecto, aquí irán hubicados 3 archivos esenciales.
  1. POTFILES.in: Listado de archivos que contienen cadenas a traducir. Si se crea vacio ejecutando
    make update-po dentro del directorio po tendrás las cadenas marcadas a trducir.
  2. POTFILES.skip: Listado de archivos que contienen cadenas traducibles pero aún se trabaja en ellos(los programadores) por lo que los traductores no deben desgatarse en ellos.
  3. ChangeLog: Lleva un control de los cambios efectuados en el proceso i18n, 110n (para ver más detalles sobre esto revise un exelente artículo publicado por la señorita Milagros Alessandra en el número 1 de la revista HD).
Además de estos 3 archivos se hubican el archivo con todas las cadenas traducibles(*.pot) y los archivos con todas las cadenas traducidas en los diferentes idiomas(*.po).
Debemos cambiar nuestro archivo configure.ac de manera que quede como en nuestro hola mundo internacionalizado(por lo que ha cambiado a la verción 0.0.2) pero es recomendable que usando las piezas de la primera verción llegues hasta la segunda siguiendo los pasos desde para que entiendas bien todo por ti mismo. Una forma cómoda de ver los cambios es usando una herramienta difftool(ej:meld), los cambio son menores y los comento a continucaión:
  • AC_PROG_INTLTOOL ( [ 0.50.2-2 ] ): Para que ./configure chequee que esta intltool en la verción especificada(como minimo).
  • GETTEXT_PACKAGE: Esta variable es usada para nombrar el paquete.
  • AC_SUBST: Publica la variable pasada como parámetro para ser usada de manera gloval en el proyecto(en cualquier Makefile.am se podrá aceder a su valor), en este caso es útil para po/Makefile.in.in.
  • AC_DEFINE_UNQUOTED: Esta macro se usa para declarar sus “parámetros” en config.h(para este caso ya que así le nombramos en AM_CONFIG_HEADER), si lo escribieramos en “C” sería: #define GETTEXT_PACKAGE “hola−mundo” que de hecho se puede observar en config.h que este es su resultado.
  • ALL_LINGUAS: Contendría los idiomas que tenemos disponibles.
  • AM_GNU_GETTEXT: Verifica que tengamos disponible gettext en nuestro sistema, además de agregar algunas entradas en config.h de manera automática.
En el archivo Makefile.am se han efectuado cambios en 3 variable de las que solo es nueva CLEANFILES en la que ponemos archivos que queremos eliminar con “make clean”. En src/Makefile.am solo es nueva INCLUDES que especifica donde estaran las cadenas traducidas. EL archivo src/hello_world_i18n.h es usado para garantizar que nuestra aplicación “siempre” compile aunque no esté disponible el soporte para internacionalización, basicamente si está _ (str) se sustituye en tiempo de preprocesamiento por ( const char ∗) gettext ( str), si no está se sustituye por si misma, o sea no es el resultado de gettext, si no el mismo parámetro lo que se optiene.
En src/main.c los únicos cambios destacables son:
  • setlocale (LC_ALL, “”); al pasarle “” nuesto progrma uasará el “locale” definido por el sistema.
  • bindtextdomain ( GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR ); :Aquí usamos el valor establecido en src/Makefile.am.
  • bind_textdomain_codeset ( GETTEXT_PACKAGE, “UTF-8″ ); : Aquí decimos la codificaciín de caracteres que vamos a usar.
  • textdomain ( GETTEXT_PACKAGE ); define el dominio o ámbito de traducciones, normalmente reducido al dominio del programa y que se encuentra definido en GET- TEXT_PACKAGE.
La secuencia de comandos se ha modificado ligeramente:
mkdir m4 ; aclocal -I m4
autoheader
glib-gettextize --copy --force
intltoolize --copy --force --automake
autoconf
automake --add-missing
En el directorio “po” falta determinar el contenido del archivo POTFILES.in. Para ello, dentro
de dicho directorio basta invocar el comando:
cd po ; touch POTFILES.in ; intltool-update --maintain ; cd ../
esto mostrará los archivos que tienen cadenas a traducir y que no se encuentran en el archivo POTFILES.in. Para facilitar el trabajo, también se genera un archivo llamado missing(puede ser añadido al final de POTFILES.in).
./configure
cd po
make update-po
cp hola-mundo.pot es.po (Para estos archivos puedes usar Gtranslatro como explican en HD)
cp hola-mundo.pot fr.po (El francés lo dejaré sin traducir para que compruebes que la aplicación se ejecuta lo que solo en inglés)
cd ../
Traducir con Gtranslator(recomendación). Finalmente, tras ejecuta make dist, se tendrá la versión 0.2 del programa hola-mundo.
NOTA:
Para probar el prgrama debes tener los “locales” instalados (apt-get install locales-all), además la variable de entorno en el idioma que quieres, ej: export LANG=”es_ES.UTF-8″, deberás tener en cuenta que para este caso deberás instalar el progrmaa (sudo make install) por el lugar donde se ha especificado buscar los *.mo además debes establecer la codificacion de caracteres ej:UTF-8, si usas Gtranslator esto parecería tribial pero es muy importante. Por último la descarga de este ejemplo para que te guies y no te suene ambiuguo lo que he explicado, una tecnica puede ser usr una herramienta diff si ya habias entendido bien el ejmplo anterior.


git clone https://github.com/denisacostaq/EmbeLinux --branch hello-intltool

miércoles, 18 de septiembre de 2013

Autotools(1). Hola mundo a la autotools.

En lo que sique(incluido este como el primero) estaré publicando una serie de posts relacionados con la creación y configuración de proyectos basados en el grupo de herramientas de autotools(antes es aconsejable revisar el directorio /usr/share/doc/gnu-standards, de este no existir ejecuta apt-get install gnu-standards y además ver también este enlace a wikipedia) y algunas otras que se le integran muy bien, además mencionar que me basaré en los lenguajes C/C++ pero que bien se adapta a otro tipo de lenguajes como son C, C++, Java, Python, Fortran, Yacc, awk, etc.
Primero que todo veamos la estructura básica de un proyecto, los directorios y archivos principales que lo componen y después veremos como editamos estos últimos para lograr un proyecto muy básico, nuetro “hola mundo”.
Estructura básica:
Escojemos un directorio en el cual relizaremos nuestro trabajo y ejecutamos la siguiente secuencia de comandos para crear las bases del proyecto.
mkdir -p hola_mundo/src
cd hola_mundo/
touch Makefile.am configure.ac src/Makefile.am src/hello-world.c NEWS AUTHORS ChangeLog README MAINTAINERS HACKING VERSION THANKS TODO

Ejecutando el comando tree -v(man tree) ya visualizamos la estructura actual del proyecto (Fig 1) donde tenemos los archivos principales de información, (compuesto por 2 grupos, los obligatorios Fig 2 (aquí faltan COPYING e INSTALL lo que no los pondré ya que autotools te propone los correspondientes que deberás editar para adptarlo a las necesidades de tu proyecto) y los opcionales (Fig 3)), los archivos inherentes a las herramientas de autotools también llamados de configuración (Fig 4), y por su puesto los archivos/directorios donde estará el código fuente(en este caso solo uno).



Como contenido de estos archivos (los de información) se tiene una explicación sobre si mismos que se puede ver en un link que dejo al final con un ejemplo.
Edición de los archivos de configuración de autotools:
#configure.ac
AC_PREREQ([2.69])
AC_INIT([hola-mundo],[0.0.0], [denisacostaq@gmail.com], [hola_mundo], [blogspoot.com/embelinux])
AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE([1.10.1])
AC_PROG_CC
AC_OUTPUT([Makefile src/Makefile])
Comentaré superficialmente el contenido de este archivo, para una información más detallada ver /usr/share/doc/autoconf-doc/ (apt-get install autoconf-doc), este archivo se escribe en M4.
- AC_PREREQ advierte sobre la verción mínima de autoconf con que debe contar tu sistema (autoconf –version, para saber que valor poner en tu caso).
- AC_INIT tiene como parámetros el paquete, la verción, el e-mail de reporte de bugs, el nombre de empaquetamiento y la url del proyecto en ese orden y no siendo obligatorios todos estos parámetros.
- AC_CONFIG_HEADERS dice donde poner el archivo config.h(que puede tener otro nombre) el cual puede ser usado en el código de nuestro proyecto.
- AM_INIT_AUTOMAKE automake y especificamos que verción (automake –version). Se pueden escribir macros para automake, estas comienzan con el prefijo AM_ .
- AC_PROG_CC especificamos que usaremos el compilador de c y se le pudiera pasar un lista de comprobación, sino la pasamos autoconf comprueba usando una que tiene internamente.
- AC_OUTPUT especificamos los lugares en que queremos un Makefile(también se pueden obtener otros ficheros) como salida.
#Makefile.am
SUBDIRS = src
EXTRA_DIST =  README THANKS TODO HACKING MAINTAINERS
Para este archivo se puede leer el manual GNU Automake.
- SUBDIRS especifica los directorios por los que se debe mover make, es aproximadamente el orden que sequirá el “topological sort”.
- EXTRA_DIST es para incluir en el empaquetado archivos que no son indispensables en el proyecto.
#src/Makefile.am
bin_PROGRAMS = hola-mundo
hola_mundo_SOURCES = hello-world.c
En la variable bin_PROGRAMS especificamos el o los programas binarios que se van a crear. Después como muestra hello_world_SOURCES especificamos el código fuente a partir del cual se creará cada binario fijandote en tranformar el nombre del binario a su forma canónica, ej:hola-mundo -> hola_mundo y agregandole el sufijo _SOURCES.
Una vez editados estos archivos de configuración de proyecto ponemos el código, ej: printf (“hello world\n”); y por último coenzamos a invocar a las herramientas de autoconstrucción.
aclocal
autoheader
autoconf
automake -a (con la opcion -a no pone el archivo COPYING(enlace a /usr/share/automake-1.13/COPYING) e INSTALL(enlace a /usr/share/automake-1.13/INSTALL) como ya había mencionado)
./configure (en este punto se chequea si nuesto sistema está preparado para compilar el programa, por ejemplo desintala el compilador y verás lo que sucede).
make (ya podemos ejecutar nuestro programa que se llama hello_world y está en src).
La llamada a aclocal busca todas las macros m4 en todos los archivos *.m4 en el directorio donde se ejecuta y finalmente en configure.ac poniendolas todas juntas en el archivo aclocal.m4 que genera. El comando autoheader crea el archivo.h.in, autoconf es el responsable de crear el archivo(scrip) configure, automake genera los archivos Makefile.in ,y por ultimo ./configure es quien genera los Makefile a partir de Makefile.in y config.h a partir de config.h.in. A modo de resumen, se muestra en el siguiente diagrama el flujo del funcionamiento de las herramientas (Fig 5).
Fig 5
Adicionalmente podemos ejecutar como root make install que instala nuestro programa en el sistema, por defecto en /usr/local, podemos modificar esto volviendo a ejecutar ./configure pero esta vez con el parametro –prefix=PATH. También podemos ejecutar make dist y nos empaqueta el proyecto.
Como nota adicional comentar que debes tener todas estas herramientas en tu sistema para trabajar con autotools pero una vez que tengas el empaquetado solo necesitas los compiladores, bibliotecas, frameworks y todo de lo que dependa tu programa para compilarse pero no las herramientas con las cuales creates el paquete, o sea ya podrás ejecutar el clásico ;) (./configure ; make ; sudo make install).

git clone https://github.com/denisacostaq/EmbeLinux --branch hola-mundo

sábado, 15 de junio de 2013

firmware-stm3210fx3 "SEE" Un proyecto plantilla en autotools para STM32EVAL10X

Con esta plantilla tienes la oportunidad de trabajar con la biblioteca de periféricos STM32F10x_StdPeriph_Lib y el kernel FreeRTOS.

 git clone https://github.com/denisacostaq/firmware-stm3210fx3.git

firmware-stm3210fx2 "SEE" Un proyecto plantilla en autotools para STM32EVAL10X

Con esta plantilla tienes la oportunidad de trabajar con la biblioteca de periféricos STM32F10x_StdPeriph_Lib.

git clone https://github.com/denisacostaq/firmware-stm3210fx2.git

firmware-stm3210fx1 "SEE" Un proyecto plantilla en autotools para STM32EVAL10X

Esta plantilla es la más básica de todas, solo te garantizo que compila pero el resto deberás agregarlo tú.

git clone https://github.com/denisacostaq/firmware-stm3210fx1.git

Un proyecto plantilla en autotools para STM32EVAL10X.

Bueno, bueno, ya con el título tienen “el gran trabajo” en este post, simplemente una plantilla que me cansé de escribir por decenas de veces que lo había hecho. El tema consiste en que por acá usamos las normas de gnu para el desarrollo de aplicaciones y esto incluye la configuración del proyecto por su puesto(see GNU Coding Standards). Como IDE puedes usar el de tu preferencia (el que tenga soporte para autotools o sea casi todos), como compilador usas igual el que quieras lo que tendrías que realizar cambios menores en la configuración del proyecto(AC_PROG_CC([arm-none-eabi-gcc]) ;) ). Bueno si este post forma parte de tus intereses para el trabajo que estás realizando te dejo algunos detalles de como usar las plantillas; si no manejas la herramientas autotools probablemente no te sea útil.
Primero que todo veamos como compilar y “flashar” en memoria estas plantillas que no hacen nada pero bueno por lo menos se ejecutan jeje.
  1. tar -xvzf firmware-stm3210fx#.tar.gz
  2. cd firmware-stm3210fx#-0.0.0
  3. export PATH=$PATH:/path/a/tu/toolchain
  4. ./configure –host=arm-none-eabi
  5. make
  6. make flash_firmware
Fácil verdad!,  ahora veamos algunos truquillos incluidos que te pueden facilitar la vida…
  1. doc: make doxygen-doc Te construye la documentación basada en el código si escribistes para doxygen además.
  2. “browse”: ./show_sources.sh Cada vez que en tu proyecto incluyas un nuevo archivo deberás hacerlo también en la configuración de autotool, si es un archivo de código propio lo harías en las variables “SOURCE” y “HEADER” respectivamente además por organización sería bueno que lo mantuvieras bajo “$(top_builddir)/src/Source” solo por organización, en realidad puedes ponerlo donde quieras, el otro caso sería el que incluyas código freeRTOS, lwIP, STM32Peripheral, o el que sea que incluyas con el scrip mencionado puedes tener una vista inmediata de donde se encuentra exactamente para agregarlo a su correspondiente variable (FREERTOS_SOURCE, ST_LIB_SOURCE, …), y tener en cuenta que si el compilador no está buscando cabeceras en el directorio recién incluido, incluirlo! en la variable AM_CPPFLAGS.
  3. Flashar: make flash_firmware Flashea la memoria usando una interfaz JTAG y openocd.
  4. Tablas de símbolos: cd src ; make log ; cd ../ , en src estarán los ficheros (*.txt) con tablas de símbolo, espacio de memoria, … que tal vez en algún momento necesites mirar.
  5. Detalles de compilación: make details Esto te muestra la compilación que estás realizando, para este caso específico la salida sería; Building from:
    build_cpu = i686, build_os = linux-gnu, build_vendor = pc
    To:
    host_cpu = arm, host_os = eabi, host_vendor = none
  6. Por último ten en cuenta que de una manera u otra terminarás modificando las reglas de compilación por lo que he copiado en doc/file.txt algunos de los parámetros utilizados, por ejemplo el proyecto está configurado en modo debug (-g), cuando hagas liberación esta bandera debería ser deshabilitada. Más información al respecto la buscas en la especificación de tu compilador.
Espero te sea de ayuda y si bien no sirve para cualquier proyecto, tengas una buena idea de como usar autotools :)

Ver además:
firmware-stm3210fx1
firmware-stm3210fx2
firmware-stm3210fx3