viernes, 20 de enero de 2012

El meollo de las librarias y el proceso de linkeo en C++

Uno de los compiladores más completos que cumple con todas las normas ISO de C++ Gcc sobre linux. Y quiero compartir lo que he aprendido en los últimos años de programación.
Lo primero que siempre me costo es el linkeo y que es este condenado proceso:
Bueno el linkeo es el paso de anexar bibliotecas a nuestro código objeto (Source code compilado) generando una imagen binaria.
Un ejemplo hiper sencillo. El clásico holamundo.cpp

//holamundo.cpp
#include <iostream>
using namespace std;
int main() {
    cout << "Hola Mundo" << endl;
    return 0;
}
./hola


El comando genera en silencio un binario con la salida de hola (Parametro -o) del sorce code (seguido de g++)
Para correrlo simplemente usamos

g++ holamundo.cpp -o hola

Este archivo utiliza una librería implícita que es la iostream. Por ende el linkeo se da correctamente.
Pero imagina que queremos hacer algo mas complejo. Algo que necesite de librerías adicionales para trabajar. Bueno que tal si creamos una librería súper sencilla para servir de ejemplo. Con esto se aclararan muchas dudas. Pero lo primero.
Nota: La librería que vamos a crear es conocida como librería estática. Esta es un poco mas pesada. que una dinámica. Y se encuentra en ubicaciones no estandar.( /usr/include y /usr/lib). La dificultad para crear una biblioteca dinámica es nula. Pero lo dejare para futuras entradas.

//koza.h
#ifndef MENSAJE_H
#define MENSAJE_H
int getMessage();
#endif
 
//koza.cpp
#include <iostream>
#include "koza.h"
int getMessage(){
    return 25;
}

Ahora si a crear nuestra biblioteca.

g++ -c koza.cpp -o libkoza.o
ar rcs libkoza.a libkoza.o

Ahora si. La hablada. El primer comando crea un archivo objeto de nuestro source sin linkear. (comando -c). La salida (comando -o) es libkoza.o. Esto es un estándar para bibliotecas. Siempre deben empezar con lib#Nombre#.a (En el caso de las librerías estáticas).
Ahora si tenemos nuestra libreria y nuestro archivo de inlcusion.
Simulemos un ambiente de mas o menos de esta forma.
Primero nuestro archivo de ejemplo para que utilice la biblioteca.

//mostrar.cpp
#include <iostream>
#include "koza.h" //Se incluye la cabecera de esta forma porque es bilioteca estatica (dinamica es con <>)
using namespace std;
int main(){
    cout << getMessage() << endl;
    return 0;
}

Simulemos la siguiente estructura de archivos.
/home/koza/ejemplo/mostrar.cpp
/home/koza/ejemplo/include/koza.h
/home/koza/ejemplo/lib/libkoza.a
ahora si a compilar

g++ /home/koza/ejemplo/mostrar.cpp -I/home/koza/ejemplo/include/ -L/home/koza/ejemplo/lib/ -lkoza

Ahora si que sucede.
El Parámetro -I le dice la ruta de los archivos de inlcusion.
El Parámetro .L le dice la ruta de los archivos de librerías
y el comando -lkoza -> La librería a incluir es libkoza.a PORQUE? Pues por el estándar. el busca el nombre de la librería después del -l#NAME según el nombre libkoza.a.
Ese fue un ejemplo muy troglodita.
Veamos algo mas útil.
Nota: Debemos tener instaladas las bibliotecas de QT4.
Vamos a compilar un ejemplo de holamundoqt.cpp

//holamundoqt.cpp
#include <qapplication>
#include <qpushbutton>

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    QPushButton hello("Hello world!");
    hello.resize(100, 30);
    hello.show();
    return app.exec();
}

Qt es una librería para hacer muchas cosas, entre ellas interfaces gráficas.
Bueno es hora de compilar el ejemplo de arriba. Como verán se ocupan un montón de librerías. Entonces a jugar.

g++ holamundoqt.cpp -o hola -I/usr/include/qt4 -I/usr/include/qt4/QtGui -L/usr/lib/qt4 -lQtCore -lQtGui

Hay una herramienta que nos ayuda mucho a la hora de realizar linkers de nuestros programas.
Es la poderosa pkg-config.
Simplemente es una herramienta que ayuda a la hora de completar los comandos de compilación. Generando los parámetros -I -L -l necesarios para compilar.
Para conocer los paquetes instalados usamos:

pkg-config --list-all

El nombre que se genera a la izquierda es el paquete que podemos usar.
En el ejemplo de qt de arriba el siguiente comando

pkg-config --cflags --libs QtGui

Muestra la siguiente salida.
-DQT_SHARED -I/usr/include/qt4 -I/usr/include/qt4/QtGui -I/usr/include/qt4/QtCore -lQtGui -lQtCore
Es precisamente todos los comandos que escribimos arriba. Haciendo uso de esta herramienta y de los pipes. El programa de holamundoqt lo podemos compilar tambien de esta forma:

g++ holamundoqt.cpp -o hola `pkg-config --cflags --libs QtGui`

No hay comentarios:

Publicar un comentario

AEM hablemos del arquetipo 11

Cuando creamos un proyecto con AEM. Siempre es importante saber que arquetipo estamos usando. Pues esto me determinara que source, herramien...