Crear librería .so y aplicación que la utilice (linux)

Buenas!
Espero que alguien me pueda echar una manita con un tema de desarrollo de librerías para Linux.

El caso es que he desarrollado una librería dinámica que a la vez utiliza otra librería dinámica. Ahora estoy intentando utilizar mi librería en una aplicación sin mucho exito y sin llegar a entender el proceso completo de creacion de .so, inclusión de .so en mi aplicación y el uso de las funciones de mi librería en el codigo de la aplicación.

Los pasos que sigo son los siguientes (el código de mi librería no tiene "main" y está compuesta de 3 modulos .c y sus .h):
1. creo los objetos de cada modulo con
gcc -fPIC -g -c -Wall -I/usr/include/DIRlibreriaExterna modulo1.c -llibreriaExterna
gcc -fPIC -g -c -Wall -I/usr/include/DIRlibreriaExterna modulo2.c -llibreriaExterna
gcc -fPIC -g -c -Wall -I/usr/include/DIRlibreriaExterna modulo3.c -llibreriaExterna

2. creo la libreria con los objetos con
gcc -shared -Wl,-soname,libMiLibreria.so.1 -o libMiLibreria.so.1.0.1 modulo1.o modulo2.o modulo3.o -lc

3. instalo mi librería recien creada copiándola en /usr/lib
4. la enlazo con el "soname" con
ldconfig -n /usr/lib


Ahora me hago la aplicación mas tonta del mundo que simplemente llama a una función de mi librería y la compilo con
gcc -Wall main.c -o app -lMiLibreria


Y me dice que no esta declarada implicitamente la función y después que no se puede encontrar mi librería. Si añado el parametro -L para indicar done esta la libreria me ocurre lo mismo.

¿Porque no me está cogiendo la libreria??

Y otras preguntas que me surgen para entender el funcionamiento son:
Al crear mi librería pasándole la librería externa, ¿en el .so que genero están ambas librerías incluidas?
¿Para hacer la aplicación que use mi librería es necesario tener los .h de los modulos usados para crear la librería?
Y por ultimo, ¿existe alguna forma de dejar solo disponible unas funciones determinadas en mi libreria y no todas las funciones que estén contenida en ella? (una especie de export como ocurre con las DLLs.

Siento el tocho, pero llevo haciendo pruebas con lo que voy leyendo y ni me aclaro ni lo consigo ;)
Gracias por leer!!!!!
Uff.. tengo muy olvidado todo, pero bueno creo que a alguna cosa puede contestar

¿Para hacer la aplicación que use mi librería es necesario tener los .h de los modulos usados para crear la librería?


Para crear una aplicación que haga uso de tu librería son necesarias las cabeceras (ficheros .h) ya que debe saber en tiempo de compilación el número y tamaño de los parámetros de entrada y salida y el tamaño de lo que devuelve la función.

Y por ultimo, ¿existe alguna forma de dejar solo disponible unas funciones determinadas en mi libreria y no todas las funciones que estén contenida en ella? (una especie de export como ocurre con las DLLs.


Solo será visible lo que declares en el fichero de cabeceras, es mas en este fichero no debería haber nada de implementación.
Buenas, antes de nada agradecer tu ayuda.
He estado probando otras alternativas y si género la librería cómo estática no tengo problemas y puedo usarla si compilo mi aplicación indicando donde están las cabeceras y y la librería en sí.
Sin embargo debo incluir también la otra librería de terceros que uso en mi librería.
¿hay forma de que esta librería de terceros vaya empaquetada en mi librería?

He comprobado a quitar algunos prototipos de las cabeceras pero siguen siendo accesibles desde la aplicación donde incluyo mi librería. ¿No hay alguna forma de declarar las funciones públicas que deseo que tenga mi librería?

Mil gracias
gcc -fPIC -g -c -Wall -I/usr/include/DIRlibreriaExterna modulo1.c -llibreriaExterna


Esa -llibreriaExterna va en la fase de enlace, no en la de compilación.
codestation escribió:
gcc -fPIC -g -c -Wall -I/usr/include/DIRlibreriaExterna modulo1.c -llibreriaExterna


Esa -llibreriaExterna va en la fase de enlace, no en la de compilación.


OK, si solo incluyo el -I/usr/include/DIRlibreriaExterna me crea el objeto sin problemas.

Lo que no consigo es incluir la libreria externa dentro de mi libreria, para no tener que incluirla tambien en los programas que tiren de mi libreria. Es decir, que para aplicaciones que usen mi libreria, sea transparente el uso de la libreria externa que estoy usando en la mia.
Ademas que si esta libreria externa no está instalada en el sistema, no van a poder usar mi libreria

Muchas gracias
Vamos por puntos:

Para compilar el código objeto no necesitas pasarle la biblioteca externa:
gcc -fPIC -g -c -Wall -I/usr/include/DIRlibreriaExterna modulo1.c
gcc -fPIC -g -c -Wall -I/usr/include/DIRlibreriaExterna modulo2.c
gcc -fPIC -g -c -Wall -I/usr/include/DIRlibreriaExterna modulo3.c


Para compilar la biblioteca si la necesitas:
gcc -shared -Wl,-soname,libMiLibreria.so.1 -o libMiLibreria.so.1.0.1 modulo1.o modulo2.o modulo3.o -lc -llibreriaExterna


Nota: si no le pasas -llibreriaExterna igual compilará pero tus programas no podrán vincularse a MiLibreria hasta que le pases -llibreriaExterna (lo cual queda horrible ya que has pasado la dependencia al programa principal donde no corresponde).

Si te has fijado cuando instalas un paquete -dev en distros basadas en debian este instala unos enlaces simbólicos que son necesarios para compilar programas que usen esa biblioteca. Entonces lo que necesitas para que -lMiLibreria funcione es crear algunos enlaces simbolicos:

ln -s libMiLibreria.so.1.0.1 libMiLibreria.so.1
ln -s libMiLibreria.so.1.0.1 libMiLibreria.so


Entonces te quedas con lo siguiente:

libMiLibreria.so          -> libMiLibreria.so.1.0.1
libMiLibreria.so.1         -> libMiLibreria.so.1.0.1
libMiLibreria.so.1.0.1


Ahora si funcionará (-lMiLibreria busca una biblioteca llamada libMiLibreria.so, es por eso que no te funcionaba).
gcc -Wall main.c -o app -lMiLibreria


Un pequeño truco para terminar: no es necesario que muevas la biblioteca a /usr/lib, puedes compilar/ejecutar tu programa si usas la variable del entorno LD_LIBRARY_PATH apuntando al directorio actual, por ejemplo:

LD_LIBRARY_PATH=$(pwd) gcc -Wall main.c -o app -lMiLibreria
LD_LIBRARY_PATH=$(pwd) ./app


Esto es lo usan algunas aplicaciones propietarias que guardan sus bibliotecas en /opt para poder encontrarlas usando un script para poner la mencionada variable antes de ejecutar la aplicación.
Mil gracias codestation!!! Estas hecho un maestro.
Conseguí advinar que si incluía la libreria externa durante la creacion de mi libreria ya no necesitaba hacerlo en la compilacion de la aplicación. Pero ls trucos que me has puesto me vienen de perlas. Muchas gracias!!!!

Ya la ultima cosa, para aclararme las ideas del todo.
La libreria externa que uso debe tirar de algo mas, ya que para que mi aplicacion funcione incluyendo solo mi libreria (e intrinsecamente la libreria externa) debo antes instalar el demonio pcscd. Es de perogrullo que un demonio no es una libreria, pero no me queda claro el proceso completo que se realiza para que mi aplicación, tire de mi libreria, que a su vez tira de una libreria externa que hace uso de un demonio para conectar con el dispositivo hardware con el que deseo comunicarme. ¿Instalar ese demonio es la unica forma de que mi libreria pueda cominicarse con el dispositivo??? No habria una forma de incluir todo en un paquete (libreria) para que quien desarrolle aplicaciones que usen mi libreria no tengan que realizar instalación alguna???

Gracias de nuevo por tu tiempo
6 respuestas