Como ejemplo tomaremos la
creación de una biblioteca para cálculos matemáticos, primero la
haremos y usaremos estática y después compartida.
Biblioteca estática:
En una biblioteca estática tenemos una
serie de procedimientos que son comunes pero cada programa que
compilemos a partir de ella incluirá los archivos de los que use
cualquier cosa dentro de su propio código atentando contra el tamaño
del archivo binario final, no será necesario tener la biblioteca en
el entorno en que va a correr el programa.
//plus.c int plus (int sum1, int sum2) { return (sum1 + sum2); }
//mult.c int mult (int fact1, int fact2) { return (fact1 * fact2); }
Para obtener el código objeto de estas dos funciones
y/o archivos ejecutamos: gcc plus.c mult.c -c, con la
opción -c le decimos a gcc que compile o ensamble nuestro código
pero que no lo elnace (gcc se refiere a GNU Collection Compilers y/o
a GNU C Compiler, pero en este último caso aclarar que no es en
realidad gcc quien compila sino que es más bién un driver, o sea
encarga a otros programas a hacer el trabajo). Para crear la
bibliteca ejecutamos ar -r libmat.a plus.o mult.o, con esto
libmat.a queda lista para ser usada como una biblioteca estática (rm
*.o *.c).
//main .c #include <stdio.h> int plus (int, int); int mult (int, int); int main (int argc, char *argv[]) { int val1 = 2; int val2 = 5; printf (“%d + %d = %d\n”, val1, val2, plus (val1, val2)); printf (“%d * %d = %d\n”, val1, val2, mult (val1, val2)); return 0; } gcc main.c -lmat -o program (produce el siguiente error) /usr/bin/ld: cannot find -lmat collect2: error: ld returned 1 exit status
Ahora ejecutamos gcc main.c libmat.a -o program
que sí compila correctamente pero le estamos pasando la ruta de la
lib de forma explícita, la manera elegante sería diciendole a gcc
enlazate a mat(-lmat) para que él solo la busque pero no lo hemos
conseguido porque el enlazador(ld) ha buscado en los directorios que
tiene por defecto normalmente(/lib y /usr/lib más cat
/etc/ld.so.conf.d/*) así que podemos agregar nustro directorio
actual a las rutas de búsqueda con gcc main.c -L. -lmat -o
program. Una forma más elegante de compilar es usando la
variable de entorno LIBRARY_PATH, que sería así:
export LIBRARY_PATH=$LIBRARY_PATH:. gcc main.c -lmat -o program
Además para ver lo que decía sobre que gcc es un
driver podrias ejecutar gcc -### -lmat main.c -o program con
lo que gcc te dice lo que haría si le quitas -### pero no lo hace.
Biblioteca compartida:
A diferencia de una biblioteca estática
los programas que se compilan con bibliotecas compartidas (shared
object, extención .so) no incluyen el código de estas dentro de sí,
sino información de con que lib ha sido enlazado el programa de
manera que cuando el programa se va a ejecutar el linkeador
(ld-linux, no el que se usa para compilar) determina de qué
bibliotecas depende nuestro programa para estar en RAM y de faltar
alguna la carga, por ejemplo para el programa que habiamos compilado
hasta ahora podemos saber de que depende usando ldd program, deberás
notar que no depende de libmat.
Para crear una biblioteca comartida
solo tenemos que especificarle esto a gcc con shared, usando todo el
codigo que hasta ahora teniamos solo cambiaremos la manera en que
creamos la lib y el programa y veremos el impacto:
gcc -c -fPIC mult.c plus.c gcc -shared mult.o plus.o -o libmat.so gcc main.c -lmat -o program (que tendrás un error, así que resuelvelo...)
./prgram (te generará el siguiente error, ./program:
error while loading shared libraries: libmat.so: cannot open
shared object file: No such file or directory, si ejecutamos ldd
program verás que a diferencia de el caso pasado este si depende
de libmat y que además “not found”, para resolver esto tenemos
que agregar como ruta de busqueda al elnlazador ld-linux(no el de
compilar insisto), la ruta donde esté nuestra lib o mejor una
solución más pacífica export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
, con lo que puedes volver a ejecutar ldd para ver el cambio y además
ya puedes ejecutar a ./program).
Bibliotecas dinámicas:
En este punto solo mencianaré que las
bibliotecas dinámicas son una “forma” de las bibliotecas
compartidas la diferencia es que en ahora el SO no autodetecta las
bibliotecas de que depende el programa y las carga de forma
automática, es el programador quien tiene esta responsabilidad,
básicamente se cargan bajo demanda, tiene la ventaja de que la
aplicación se carga en RAM más rápidamente y el inconveniente de
que es el programador quien tiene la responsabilidad de hacer
entonces ese trabajo, pudiera ser por ejemplo usando la lib ltdl que
cuenta con funciones como dlopen.
En algún que otro post relacionado con
autotools+libtool veremos como los humanOS hacemos esto, ya que hasta
ahora solo vimos el método de los “dinosauriOS”
.