Minitutorial para crear y usar bibliotecas propias.
Como ejemplo se crea una biblioteca llamada aritmetica
con las cuatro operaciones básicas: suma
, resta
, multiplicacion
y division
.
Se realiza para los lenguajes:
- C
- Java
Codigo de biblioteca en:
A continuación veremos como:
- Crear una biblioteca estática
- Crear una biblioteca dinámica
- Usar la biblioteca dinámica como plugin
- Hacer enlace estático
- Hacer enlace dinámico
Cuando desarrollamos un programa, éste, además de compilarse, necesita enlazarse con la biblioteca estándar del lenguaje y otras bibliotecas propias del desarrollador.
En los lenguajes compilados se distingue dos tipos de enlazado con una biblioteca:
-
Estático El enlazado estático incluye el código de la biblioteca dentro del programa que hace uso de ella.
Ventajas:- Programa autocontenido.
- Las actualizaciones de la biblioteca no le afectan.
Desventajas:
- Mayor tamaño del programa.
- El programa no se beneficia de las actualizaciones de la biblioteca.
-
Dinámico El enlazado dinámico NO incluye el código de la biblioteca dentro del programa que hace uso de ella. En su lugar se realiza un vínculo a la biblioteca dinámica.
Ventajas:- Menor tamaño del programa.
- El programa se beneficia de las actualizaciones de la biblioteca.
Desventajas:
- Programa NO autocontenido.
- Las actualizaciones de la biblioteca le afectan para bien y para mal.
Hay una tercera forma de uso:
- Plugins: Carga de biblioteca en tiempo de ejecución.
Es muy parecido al enlazado dinámico, con la salvedad que se carga la biblioteca en tiempo de ejecución. Esto permite, en un caso dado, comprobar si dicha biblioteca está disponible y hacer un uso de ella según el caso. Así prevenimos el error de carga del programa que se produce cuando no se encuentra la biblioteca enlazada dinámicamente.
Lo normal es distribuir la funcionalidad básica de una aplicación en bibliotecas dinámicas y la funcionalidad opcional en forma de plugins.
- Compilamos a código objeto estático
gcc -c aritmetica.c
Se habrá generado un archivo aritmetica.o
con código objeto estático.
- Empaquetamos en biblioteca estática
libaritmetica.a
ar cr libaritmetica.a aritmetica.o
- Instalamos biblioteca en el sistema.
Desde el punto de vista del programa desarrollado, este paso no es necesario. Pero resulta adecuado si deseamos hacer disponible la biblioteca para que otros programas puedan hacer uso de ella durante su compilación y enlazado.
Para instalar dicha biblioteca en el sistema debemos copiar libaritmetica.a
a algún directorio de sistema donde se alojan las librerias (p.ej: /lib
o /usr/lib
)
cp libaritmetica.a /lib
- Compilamos a código objeto dinámico
gcc -c -fPIC aritmetica.c
Se habrá generado un archivo aritmetica.o
con código objeto dinámico.
- Empaquetamos en biblioteca dinámica
libaritmetica.so
gcc -shared -fPIC -o libaritmetica.so aritmetica.o
- Instalamos biblioteca en el sistema
Para instalar dicha biblioteca en el sistema debemos copiar libaritmetica.so
a algún directorio de sistema donde se alojan las librerias (p.ej: /lib
o /usr/lib
)
cp libaritmetica.so /lib
Codigo en:
- Compilamos y enlazamos, generando un ejecutable
plug
gcc -o plug plug.c -ldl
Además de enlazar con la biblioteca estándar de C, debemos enlazar con la biblioteca adicional dl
que nos permite la carga de código binario en tiempo de ejecución.
- Ejecutamos programa
plug
./plug
Codigo en:
- Compilamos y enlazamos, generando un ejecutable
main
y enlace estático alibarimetica.a
gcc -o main main.c libaritmetica.a
- Comprobamos vínculos dinámicos
ldd main
Observamos que NO aparece la biblioteca libaritmetica.a
como enlace dinámico.
Codigo en:
- Compilamos y enlazamos, generando un ejecutable
main
y enlace dinámico alibarimetica.so
gcc -o main main.c libaritmetica.so
- Comprobamos vínculos dinámicos
ldd main
Observamos que SÍ aparece la biblioteca libaritmetica.so
como enlace dinámico.
Una forma de distribuir un programa con enlace dinámico de forma autocontenida es distribuir la biblioteca junto al programa y hacer el enlazado con una ruta relativa. En este caso la biblioteca está en el mismo directorio que el programa.
- Compilamos y enlazamos, indicando el directorio donde está localizada la biblioteca, en este caso
.
(el propio directorio)
gcc -L. -Wl,-rpath=. -Wall -o main main.c -laritmetica
NOTA: Se hacen uso de las siguientes opciones:
-Wall Para mostrar warnings (puede quitarse si se desea)
-Wl,rpath=. Directorio donde el enlazador debe buscar la biblioteca
-L. Directorio donde se hallan los archivos de cabecera
-laritmetica Biblioteca a enlazar (libaritmetica.so: observa que se elimina el prefijo lib y el sufijo .so)
- Comprobamos vínculos dinámicos
ldd main
Ya podemos copiar main
y libaritmetica.so
juntos y main
siempre encontrará a la biblioteca.
Una forma de distribuir un programa con enlace dinámico de forma autocontenida es distribuir la biblioteca junto al programa y hacer el enlazado con una ruta relativa. En este caso organizaremos un poco la información, pondremos la biblioteca en un subdirectorio llamado libs
.
- Creamos subdirectorio y movemos biblioteca a él.
mkdir libs
mv libaritmetica.so libs
- Compilamos y enlazamos, indicando el directorio donde está localizada la biblioteca, en este caso
./libs
(el subdirectorio del mismo nombre)
gcc -L./libs -Wl,-rpath=libs -Wall -o main main.c -laritmetica
- Comprobamos vínculos dinámicos
ldd main
Ya podemos copiar main
y libs/libaritmetica.so
juntos y main
siempre encontrará a la biblioteca.
- Creamos directorio
aritmetica
mkdir aritmetica
- Creamos clase
aritmetica/Aritmetica.java
Codigo en:
- Compilamos
javac aritmetica/Aritmetica.java
Obtenemos un archivo aritmetica/Aritmetica.class
con el bytecode.
- Creamos paquete jar
jar cvf aritmetica.jar aritmetica/*.class
- Instalamos biblioteca en el sistema
Para instalar dicha biblioteca en el sistema debemos copiar aritmetica.jar
al directorio de sistema donde se alojan las librerias de extensiones (p.ej: /usr/lib/jvm/default-java/jre/lib/ext
). No es necesario mantener el nombre del archivo.
mv aritmetica.jar /usr/lib/jvm/default-java/jre/lib/ext/aritm.jar
- Creamos archivo
Main.java
Codigo en:
- Compilamos
javac -cp aritmetica:. Main.java
Obtenemos un archivo Main.class
con el bytecode.
NOTA: Hacemos uso de la siguiente opción:
-cp aritmetica:. Indicamos la ruta para archivos class (classpath).
En este caso el directorio aritmetica y el directorio actual.
En Windows la separación se hace con ; en lugar de :
Si en lugar de usar el código disponible en nuestro directorio de trabajo, queremos enlazar con el del sistema (/usr/lib/jvm/default-java/jre/lib/ext/aritm.jar
) podemos simplificar la compilación de la siguiente manera:
javac Main.java
- Ejecutamos
java Main
- Creamos paquete jar
jar cvfe main Main Main.class aritmetica/*.class
NOTA: Los argumentos son:
main El nombre de archivo jar generado (opción f)
Main La clase principal o punto de entrada (opción e)
Main.class y aritmetica/*.class Los archivos bytecode a incluir en archivo jar
Las opciones f y e deben introducirse en el mismo orden que los argumentos correspondientes.
- Ejecutamos
java -jar main
NOTA: En este caso NO hemos hecho uso de la biblioteca /usr/lib/jvm/default-java/jre/lib/ext/aritm.jar.
Hemos usado el código disponible en nuestro directorio de trabajo.
Podemos mover el programa main a otro directorio o incluso a otro computador que disponga de JRE y seguirá ejecutándose correctamente.
NOTA: Otra forma de realizar la ejecución, que funciona algunas veces es: 2. Damos permisos de ejecución
chmod +x main
- Ejecutamos
./main
Para ver como automatizar el proceso de construcción (build) consulta el siguiente enlace