Avui he integrat libtool a ACR. El suport encara no està acabat, pero ja és suficient per penjar un mini tutorial de com fer llibreries en C utilitzant libtool i ACR.
Per exemplificar-ho faré una petita llibreria amb dues funcions totalment inutils, aixi la relació esforç/productivitat estarà equilibrada amb la resta del dia, per tal de mantenir-me constant... oohhm x)
.. no, definitivament no puc postejar fumat ..
Aixi que anem a fer l'estructura del projecte:
console:
$ cat src/file1.c
#include <stdio.h>
void do_something()
{
printf("Doing something\n");
}
$ cat src/file2.c
#include <stdio.h>
void do_another_stuff()
{
printf("Doing another stuff\n");
}
$
Ara haurem de definir les rules en el configure.acr, haurem de tenir en compte certs aspectes del nostre projecte i volcarlos en el
configure.acr:
console:
$ cat configure.acr
PKGNAME libtest
VERSION 1.0.2
USE_LIBTOOL!
SUBDIRS . src ;
REPORT LIBTOOL_CC LIBTOOL_SHARED LIBTOOL_INSTALL ;
Fem un repas a tots els keywords que hem utilitzat:
PKGNAME : Definim el nom del paquet que anem a crear.
VERSION : Definim el numero de versió del paquet que anem a fer.
USE_LIBTOOL! : Indiquem a ACR que volem utilitzar libtool. (L'admiració serveix, al igual que en moltes altres keywords de acr per indicar que es necessari, i que si no ho té aturi l'execució de l'script mostrant un error.
SUBDIRS . src ; : Li indiquem el llistat de directoris on trobara fitxers amb el nom 'Makefile.acr' per filtrar-los i crear els finals 'Makefile'.
REPORT LIBTOOL_CC LIBTOOL_SHARED LIBTOOL_INSTALL ; : Aquesta keyword ens creara un report al final de l'execució del ./configure final, ens ajudara a entendre millor que fa internament.
Molt bé, ara haurem de crear els 2 Makefile.acr, un en el directori actual
./ i un altre a
src/.
console:
$ cat Makefile.acr
all:
cd src & ${MAKE} all
install:
cd src & ${MAKE} install
clean:
cd src & ${MAKE} clean
mrproper: clean
rm src/Makefile Makefile
$ cat src/Makefile.acr
LIB_VERSION=@VERSION@
LIBTOOL_CC=@LIBTOOL_CC@
LIBTOOL_SHARED=@LIBTOOL_SHARED@
LIBTOOL_INSTALL=@LIBTOOL_INSTALL@
LIBDIR=@LIBDIR@
LIBNAME=@PKGNAME@
%.lo:%.c
${LIBTOOL_CC} $<
all: file1.lo file2.lo
${LIBTOOL_SHARED} ${LIBNAME}.la file1.lo file2.lo
install:
mkdir -p ${LIBDIR}
${LIBTOOL_INSTALL} ${LIBNAME}.la ${LIBDIR}
clean:
-rm -rf .libs
-rm *.o *.lo *.la
El primer dels dos Makefiles no té més secret, no crec que calgui explicar que fa. El segon ja és un pel més complexe i és exactament on intervé la veritable mecanica del framework.
Al principi de tot definim totes les variables necessaries per compilar una llibreria compartida (shared), que són:
LIB_VERSION : Variable definida per l'usuari i que es requerida per LIBTOOL_SHARED, es molt important definir-la ja que sense ella donarà error al compilar i ACR no pot manejar aquest tipus d'error, ja que ja ho fa AMR i en aquest cas hem delegat la feina a l'usuari.
LIBTOOL_CC : Compilador a utilitzar quan volguem compilar un objecte per la llibreria.
LIBTOOL_SHARED : Linkador a utilitzar quan volguem juntar els objectes de la llibreria i crear la llibreria final.
LIBTOOL_INSTALL : Ens serveix per instal.lar la llibreria, crear els noms de fitxers de la forma correcta amb el numero de versió, els enllaços simbolics, el .a (archive) i el .la (libtool archive).
LIBDIR : Definim la variable LIBDIR directament adquirida desde l'ACR, aquesta variable pot ser definida per l'usuari fent './configure --libdir=/our/new/library/path' o per defecte ${PREFIX}/lib. Serà on instal.larem la llibreria.
La primera rule potser us sembla extranya..ja que no s'acostuma a utilitzar perquè GNU-make ja integra certes d'aquestes macros per alguns tipus de fitxers, pero sembla que no suporta libtool
missfeature found!.
Aquesta macro pinta algo com aixo:
%.lo:%.c \ ${LIBTOOL_CC} $<. Aquesta macro ens serveix per indicar al make que cada cop que li demanem una dependencia d'un target que acabi amb .lo, ens agafi el .c i el compili utilitzant ${LIBTOOL_CC}, és a dir, el compilador de libtool. (un vil wrapper del CC).
Al utilitzar LIBTOOL_CC ens farà dues compilacions per cada objecte, una en el directori dels sources (o actual, si fem un crosspathbuild) amb una compilació normal i després una altre en
mode PIC a .libs.
El mode PIC serveix per fer que el loader carregui els simbols de forma dinamica, evitant el limit definit pel GOT. Aixo no està suportat en certes arquitectures, però és recomenable d'utilitzar quan creem llibreries.
--
Ara executarem l'ACR i el ./configure
console:
$ acr
acr: ./configure script created succesfully.
acr: all done.
$ ./configure
checking build system type... i686-unknown-linux-gnu
checking host system type... i686-unknown-linux-gnu
checking target system type... i686-unknown-linux-gnu
checking for working directories... current
using prefix /usr/local
checking for c compiler... gcc
checking for libtool... /usr/pkg/bin/libtool
creating ./Makefile
creating src/Makefile
cleaning temporally files... done
Final report:
- LIBTOOL_CC = /usr/pkg/bin/libtool --mode=compile gcc -c
- LIBTOOL_SHARED = /usr/pkg/bin/libtool --mode=link gcc -rpath /usr/local/lib -release ${LIB_VERSION} -o
- LIBTOOL_INSTALL = /usr/pkg/bin/libtool --mode=install /usr/bin/install -c
$
Aqui podem veure com LIBTOOL_SHARED ens demana LIB_VERSION

.
Molt bé, ara simplement fem make i veurem com tot es compila correctament. A l'hora de la creació de la llibreria, podem definir una versió i informacó dins de la versió.
Lo primer es simplement el numero de versió de la llibreria (libfoo-2.9.0.so). Pero lo segon es també interessant, ja que ens permet definir dos tipus de versions, una d'evolució (M.m.s) i la segona que especifica l'estat d'implementació per estar acabada (C:R:A) . Més concretament:
C : Current : El numero de l'implementació de l'interficie últim.
R : Revision : Nombre d'implementació de l'interficie actual.
A : Age : Diferencia entre Current i Revision.
De fet el resultat final es guiarà per aquestes premises:
console:
A < C
X = C - A
Y = A
Z = R
Per exemple: -version-info 3:0:2 resultarà en libfoo.so.1.2.0
Libtool definirà el nom final de la llibreria com: libname-V.V.V.so.X.Y.Z.
Per definir aixo ho farem amb la flag -version-info 3:0:2, encara que no es necessari i sembla que sigui una cosa que va a gustos

Té més del que sembla...feu-vos una repasada pel /lib i /usr/lib
Us pastejo finalment el output del make i aixi us feu una idea per si algo va malament
console:
$ make
cd src & make all
make[1]: Entering directory `/tmp/libtest/src'
/usr/pkg/bin/libtool --mode=compile gcc -c file1.c
mkdir .libs
gcc -c file1.c -fPIC -DPIC -o .libs/file1.o
gcc -c file1.c -o file1.o >/dev/null 2>&1
/usr/pkg/bin/libtool --mode=compile gcc -c file2.c
gcc -c file2.c -fPIC -DPIC -o .libs/file2.o
gcc -c file2.c -o file2.o >/dev/null 2>&1
/usr/pkg/bin/libtool --mode=link gcc -rpath /usr/local/lib -release 1.0.2 -o libtest.la file1.lo file2.lo
gcc -shared .libs/file1.o .libs/file2.o -Wl,-soname -Wl,libtest-1.0.2.so -o .libs/libtest-1.0.2.so
(cd .libs & rm -f libtest.so & ln -s libtest-1.0.2.so libtest.so)
ar cru .libs/libtest.a file1.o file2.o
ranlib .libs/libtest.a
creating libtest.la
(cd .libs & rm -f libtest.la & ln -s ../libtest.la libtest.la)
make[1]: Leaving directory `/tmp/libtest/src'
$
>>
ACR
>>
Libtool manual
[add comment] [view comments] (38)