Manual
logo



Programación C++ con AGU desde 0

Compilación, enlazado, make,...

Este apartado tiene cierta dificultad para aquellos que se inician en C++, la idea es que el código fuente (archivo de texto) hay que convertirlo en un programa ejecutable (código máquina), esto en aplicaciones extensas entraña cierta dificultad, pero afortunadamente Anjuta lo hace por nosotros. Con ello, pagamos un precio, aparecen muchos archivos en nuestro proyecto que no son código fuente.

De código fuente a archivo ejecutable

El código fuente escrito en C++, no deja de ser un archivo de texto incomprensible para el microprocesador. Es necesario pasar este texto escrito en el lenguaje C++ al lenguaje comprensible por el ordenador: el código máquina.
Este proceso se denomina compilación.
La compilación requiere normalmente dos pasos: el compilado en sí, donde el código fuente se convierte a código máquina, y el enlazado (linker), donde distintos códigos objetos son enlazados para construir un archivo ejecutable.
Lo normal es que una aplicación la compongan una serie de archivos, de lo contrario el código fuente sería un archivo enorme, con el que sería muy difícil trabajar.
La compilación de C++ incluye un paso previo, que es el preprocesado. En C++ se distinguen dos tipos de texto, las directivas del preprocesador y el código en sí. El primer paso es coger estas directivas (que se caracterizan por empezar por #) e interpretarlas, pasarlas a código. Veamos un ejemplo:

Crea una carpeta en el directorio /home/usuario, por ejemplo programauno. En él edita el siguiente código (con el editor de textos) y grabalo como kk.cc:

#define ketonta 1
int main ()
{
 int x=10;

 x= x*ketonta;
return 0;
}


Abrimos un terminal [Aplicaciones->Accesorios->Terminal], en éste, nos vamos al directorio de trabajo, y ejecutamos la primera fase del prepocesado:
~$ cd /home/usuario/programauno
~/programauno$ g++ -E kk.cc > prepocesado.txt

Observarás que en la carpeta se ha creado un archivo de texto - de nombre prepocesado.txt -que básicamente sustituye el sinónimo establecido en el programa con la directiva define.
compilacion
El siguiente paso, es la compilación en sí, pasar el código fuente  a código objeto, lo cual se puede realizar así:
~/programauno$ g++ -c kk.ccse creará un kk.o que no podrás editar como archivo de texto, pues es un binario (debes instalar un editor como bless).
Si alguna vez deseamos "pulir" nuestro programa en ensamblador, yo nunca lo he hecho, pero más de una vez leí sobre ello (con antiguos procesadores, microchips programables), podemos obtener la versión en ensamblador con:
~/programauno$ g++ -S kk.cc te aparecerá un nuevo archivo kk.s con el código en ensamblador, lo cual es más inteligible que el código objeto.

Un último paso es el enlazado, que nos permite la creación de un ejecutable. Antes de proceder vamos a borrar todos los archivos anteriores y reeditamos kk.cc con el siguiente texto, para que el programa haga algo (no te preocupes si ahora no lo entiendes).
#include <iostream>
#define ketonta 2
int main ()
{
 int x=10;
 x= x*ketonta;
 std::cout<<" el doble de 10 es: "<<x<< std::endl;
 std::cout<<" ¡¡ Que tontá !!"<<std::endl;
return 0;
}

Vamos a preprocesar y compilar en un primer paso (obtendremos kk.o) [si preprocesas únicamente verás porque razón utilizamos el programa anterior] y luego vamos a enlazar:
~/programauno$ g++ -c kk.cc
~/programauno$ g++ kk.o

Te aparecerá un nuevo archivo a.out, éste es un archivo ejecutable. Para ejecutarlo, desde la consola, lo llamamos, pero recuerda que si pongo solo a.out el sistema busca en los directorios de ejecutables del sistema y nos da un error [bash: a.out: orden no encontrada], es necesario buscar en el directorio actual, por lo que escribimos ./a.out, y obtendremos la siguiente salida:
 ~/programauno$ ./a.out
 el doble de 10 es: 20
 ¡¡ Que tontá !!
~/programauno$

Ahora, renombro este archivo a mi gusto y se acabó.

Todo en uno
En realidad, g++ nos permite realizar todo en un paso:
g++ -o minombre kk.ccy obtendremos un programa ejecutable con el archivo minombre.

Volviendo al enlazado existen dos posibilidades, que este sea estático o dinámico. El enlazado estático implica que las funciones de una librería externa se incorporan a nuestro ejecutable, no siendo necesario las mismas para su ejecución (por si luego ejecutamos nuestra aplicación en otro ordenador donde no tenemos acceso como root y no podemos instalar las librerías); mientras que en el dinámico, opción por defecto, la aplicación requiere la existencia en el ordenador de las librerías.
Para realizar un enlazado estático utilizamos:
g++ -static -o minombre2 kk.cc
Si observas la diferencia entre minombre, 8,8 Kb, y minombre2, 1,2Mb, verás porque normalmente los programadores utilizan el enlace dinámico.

Para una aplicación con varios archivos, la compilación se realiza:
g++ -o nombreejecutable archivo1.cc archivo2.cc archivo3.cc archivon.cc

Make y makefile

Antes hemos visto que se puede realizar todo el proceso en una sola fase, así es, pero no es lo habitual.
La razón es muy sencilla, cuando un programa tiene varios archivos y modificamos uno, en la compilación se vuelven a compilar  todos otra vez, aunque no se hayan modificado. Esto en pequeños programas no tiene mayor problema, pero cuando éste alcanza cierta dimensión, la pérdida de tiempo es considerable.
Por ello, se ideo una compilación separada donde al realizar una pequeña modificación solo se compilan los archivos afectados y no todos. Y este es el propósito del comando make. Cuando en un directorio, ejecutamos make, él busca rápidamente las reglas de compilación establecidas en el archivo makefile.

No es el propósito de este manual explicar (por ahora) como escribir los makefile, porque precisamente Anjuta se va a encargar de eso por nosotros.