Archivo para la categoría ‘Compiladores’

Desarrollar librerías en linux usando otras librerías (y sus curiosos efectos)

Después del pequeño tostón del otro día donde se comentaba la ruta de las librerías en Linux, hoy toca comentar el gran tostón de cómo se desarrollan librerías que usen otras librerías y varios efectos durante el enlazado. Si no estáis muy interesados en el desarrollo de librerías en Linux no sigáis leyendo porque quizás me odiéis. Y si sí desarrolláis librerías… bueno, quizás tampoco deberíais seguir… quedáis avisados.

Lo primero, una descripción rápida de como programar una libraría en Linux:

Creas el archivo de código fuente, por ejemplo mylib.cpp, para luego compilarlo con la opción del compilador de generar código independiente de la posición (PIC):

$ g++ -Wall -fPIC -c mylib.cpp

Luego enlazas todos los archivos objeto resultantes (*.o) en el binario de la librería indicándole al linker, además, el nombre de la librería (soname):

$ g++ -shared -Wl,soname,libmylib.so.0 -o libmylib.so.0.1 *.o

Una vez hecho esto se puede instalar la librería en algún directorio como /usr/local/lib u /opt/lib, aunque no es necesario para hacer estas pruebas.

Para usar la librería, basta con crear un programa, por ejemplo myprog.cpp, y enlazar esta librería en él. Eso sí, no os olvidéis de indicarle al compilador dónde están los archivos de cabecera (con la opción -I) y de exportar la variable LD_LIBRARY_PATH indicando el directorio de vuestra librería (como vimos el otro día):

$ g++ -I/path/to/mylib/include -o myprog -lmylib myprog.cpp

Una vez tenemos la librería y nuestro programa que la usa vamos con los curiosos efectos:

En el caso de que nuestra librería use otra librería de forma interna, a la hora de compilar es necesario indicarle donde están los archivos de cabecera de la librería a usar (opción -I) pero no es necesario indicarle, a la hora de enlazar, la librería con la que enlazar:

$ g++ -Wall -fPIC -I/path/to/otherlib/include -c mylib.cpp
$ g++ -shared -Wl,soname,libmylib.so.0 -lotherlib -o libmylib.so.0.1 *.o

A la hora de compilar nuestro programa con nuestra librería enlazada de la forma anterior, es necesario que enlacemos nuestro programa a la otra librería, sino ni siquiera enlazará porque no se pueden resolver los símbolos de otherlib que usa mylib. Por ello nuestro programa se compilaría:

$ g++ -o myprog -lmylib -lotherlib myprog.cpp

En caso de enlazar mylib con otherlib (usando la opción -lotherlib antes comentada), no sería necesario enlazar myprog con otherlib. Resumiendo este tostón incomprensible: hay que enlazar nuestro programa con todas las librerías que use y todas las que usen éstas y no lo estén ya en las mismas, aunque siempre es mejor enlazar cada cosa con lo que utiliza.

Un ejemplo:

  • Compilo mylib sin enlazar con otherlib:
    • Compilo myprog enlazando a mylib: error porque no enlaza con otherlib.
    • Compilo myprog enlazando a mylib y otherlib: todo correcto.
  • Compilo mylib enlazando con otherlib:
    • Compilo myprog enlazando a mylib: todo correcto porque, aunque hace uso de otherlib, esta ya está enlazada en mylib.
    • Compilo myprog enlazando a mylib y otherlib: todo correcto aunque innecesario porque otherlib ya está enlazada con mylib.

Buf… bueno, yo lo entiendo porque me ha pasado y he investigado un rato para resolverlo, pero visto aquí, así, sin anestesia… pues cuesta. Pero bueno, aquí queda por si en un futuro se me olvida. Y para quién le sea útil, por supuesto.