Mostrando entradas con la etiqueta biblioteca compartida. Mostrar todas las entradas
Mostrando entradas con la etiqueta biblioteca compartida. 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

martes, 19 de noviembre de 2013

Creación de bibliotecas mediante el uso de libtool (Parte 2).

Si ya revisaste el post anterior sobre construcción de bibliotecas podremos proseguir con el hecho de que ya tenemos algunos conceptos básicos de nuestro lado, esta vez relizaremos el mismo ejemplo lo que cambia es las herramientas. Primero construiremos la lib estática, después compartida y por último de ejecución (que no es más que la misma biblioteca compartida lo que se carga en tiempo de ejecución).

Libtool:
Según su propia documentación (apt-get install libtool-doc) fue diseñado desde sus inicios para soportar un número arbitrario de tipos de bibliotecas, más tarde se ha ido portando a otras plataformas y gradualmente se han ido desarrollando nuevos paradigmas que describen la relación entre las bibliotecas y los programas.

Consideremos el sigiente código con el cual crearemos la biblioteca estática y compartida:
//module.c
float mult (float fac1, float fac2)
{
return fac1 * fac2;
}

Biblioteca estática:
1. Creamos un directorio donde “instalaremos” la lib.
mkdir -p /tmp/install
2. Compiamos el código.
libtool --verbose --mode=compile gcc -g -O -c module.c -static
3. Enlazamos el código, si no ponemos -rpath /tmp/install al comando anterior tendremos que ejecutar
libtool --finish /usr/local/lib después para que se complete la instalación correctamente.
libtool --verbose --mode=link gcc -module -o module.la module.lo -rpath /tmp/install -static
4. Instalamos
libtool --mode=install install module.la /tmp/install
Ya tenemos lista la lib en /tmp/install que puedes usar como en el post anteriorque mencionaba al inicio y además notar que se encuentra en el direcorio oculto (ls .libs/).

Biblioteca dinámica:
Recomendable eliminar los archivos anteriores para ver el nuevo resultado y repitiendo los pasos para este caso tenemos:
1. mkdir -p /tmp/install
2. libtool --verbose --mode=compile gcc -g -O -c module.c -shared
3. libtool --verbose --mode=link gcc -module -o module.la module.lo -rpath /tmp/install -shared
4. libtool --mode=install install module.la /tmp/install

Biblioteca de ejecución:

Para ver como usamos una lib en tiempo de ejecución usaremos el siguiente código:

#include <stdio.h>
#include <ltdl.h>
#include <stdlib.h>

//declaramos una variable(puntero a la función así que
//debe coincidir en los tipos)
float (*mult)(float fac1, float fac2);

int main (int argc, char *argv[])
{
lt_dlhandle handle;
lt_dlinit ();
lt_dladdsearchdir ("./");

handle=lt_dlopenext ("module");
if (!handle)
{
printf ("Error, módulo no cargado: %s\n",
                   lt_dlerror());
exit (EXIT_FAILURE);
}

const lt_dlinfo *info;
info = lt_dlgetinfo (handle);
if (!info)
{
fprintf (stderr, "No se pudo obtener la información  del módulo: %s\n", lt_dlerror());
lt_dlclose (handle);
exit (EXIT_FAILURE);
}
if (info->name)
{
printf ("Nombre del módulo: %s\n", info->name);
}
else
{
printf ("No es un módulo libtool\n");
}
//casteo al tipo de la función
mult = (float(*)(float, float))lt_dlsym(handle, "mult");  
if (mult)
{
printf ("Resultado desde el módulo: %f\n", mult(5.0, 10.0));
}
else
{
perror ("No se pudo cargar la función\n");
lt_dlclose (handle);
exit (EXIT_FAILURE);
}
lt_dlclose (handle);
return 0;
}


Recomendable eliminar los archivos anteriores para ver el nuevo resultado y repitiendo los pasos para este caso tenemos:
1. libtool --verbose --mode=compile gcc -g -O -c module.c -shared
2. libtool --verbose --mode=link gcc -module -o module.la module.lo -rpath /tmp/install -shared
3. libtool --mode=link gcc -export-dynamic -o programdl program.c -lltdl

Un detalle importante es notar que la lib se contruye de la misma manera que la compartida, el programa es el que se contruye de forma diferente a la convencional y además con ldd como en el post anterior puedes ver como program no depende de module por lo que los pasos 2 y 3 se pueden cambiar de orden ya que program no necesita saber nada acerca de module en tiempo de compilación.
NOTA: Para tener más referencia consulte man libtool o /usr-sha-doc-libtool-doc.