[Intro] Compilación, Linkado y Makefiles en C

Hola,

Hoy voy a hablar un poco de la compilación, el linkado y los makefiles. Todo desde mi limitado conocimiento del tema con el objetivo de introducir a los más novatillos al tema. Como siempre, el plan no es dar un speech del asunto.

Vamos a por ello.

Primero quiero diferenciar los lenguajes interpretados (Python, PHP, Perl… octave también) de los lenguajes compilados (C, C++, Pascal… incluso Java y Erlang aunque de una forma un poco diferente de la que no hablaré).

Hay muchos lenguajes de programación que son interpretados, que significa que hay un programa (un intérprete) que los lee y los va ejecutando directamente desde el código fuente (en texto). La consola de nuestro linux favorito es un caso de esto. La consola lee lo que le pedimos y ejecuta nuestras órdenes. Hoy no vamos a hablar de esto, para eso está la sección de scripts.

Los lenguajes de programación compilados, sin embargo, no requieren de un intérprete, si no que necesitan compiladores y linkers. Este caso es el que nos ocupa. Voy a intentar explicar de forma simple este proceso y enseñaros una forma de automatizarlo.

Bien. Los lenguajes de programación compilados no requieren que exista un programa que los vaya leyendo, si no que, antes de ejecutarse, deben ser traducidos a un lenguaje que la máquina sea capaz de entender directamente, sin intermediarios. En ese proceso es en el que entran los dos amigos que he mencionado más arriba. (A partir de ahora hablaré del caso concreto de C, aunque todo se puede extrapolar con facilidad a los otros casos cambiando el compilador, usando g++ para C++ por ejemplo.)

  • El primero es el compilador, o compiler. Cuando ejecutamos el compiler, éste toma nuestros archivos de código fuente y los convierte a un archivo que la máquina sea capaz de entender. Es decir, convierte un programa legible por el humano a uno legible por la máquina. Estos nuevos archivos se llaman objetos, y, en linux al menos, suelen tener la extensión .o o .obj dependiendo del compilador.
  • El segundo es el linker. El linker toma los objetos y los une para crear ejecutables. También busca las librerías que se quieran añadir, y las añade en el caso de que sean librerías estáticas (esto lo dejamos para la siguiente).

El compilador GCC (GNU C Compiler) es capaz de hacer ambas cosas e internamente hará ambas si no le especificamos lo contrario. En los proyectos un poco complicados (que tengan más de un archivo o usen librerías) así deberemos hacerlo, compilando primero y linkando después desde la consola tal que así (yo uso GCC pero podéis usar otro):

gcc -c main.c   # Crea el objeto main.o, -c indica sólo compilar
gcc main.o      # Crea el ejecutable (por defecto a.out)

Si queréis probar con un hola mundo, aquí tenéis uno rápido. Lo guardáis en como main.c y listo, podéis ejecutar lo anterior:

#include<stdio.h>

void main(int argc, char * argv[]){
    printf("hola!\n");
}

Ahora que ya tenéis el ejecutable podéis ejecutarlo:

~$ ./a.out
hola!
~$

Si lo hubiésemos hecho sin el -c en la primera orden hubiese sacado el a.out directamente, pero no queremos eso porque en proyectos grandes será interesante que no linke hasta que nosotros se lo pidamos ya que querremos añadir librerías, etc.

Ya veis como se hace, pero tenemos que entender que en programas grandes con varios archivos hacer esto por cada uno de ellos y luego linkar todos los .o en un único ejecutable puede ser la muerte. Para evitar eso existe la herramienta Make.

Make es una herramienta supercremas[1]. Nos ayuda en esta labor permitiéndonos definir en unos archivos llamados Makefiles el orden en el que queremos que las cosas se compilen y linken (aunque también sirve para muchas más cosas). Una vez definidos estos archivos con lanzar la orden make él mismo sabrá como debe actuar[2].

El Makefile tiene entradas de la siguiente forma:

objetivo: requisitos
    receta para conseguirlo

Si aplicamos esto a lo que hemos explicado más arriba, podemos decir en el makefile que para conseguir el ejecutable necesitamos los objetos y que para conseguir los objetos necesitamos los archivos de código fuente. Además, en las recetas es sencillo saber qué hace falta. Para conseguir los objetos tenemos que compilar el código fuente, con la orden que he dicho antes, y para conseguir el ejecutable tendremos que linkar los objetos necesarios, con la segunda orden que he puesto. Dejándolo tal que así:

all: a.out       # Esto es lo que hará por defecto

a.out: main.o
	gcc main.o

main.o: main.c
	gcc -c main.c

Si creamos un archivo llamado makefile (o Makefile) con el contenido mostrado y lanzamos el comando make haremos las dos partes que he mencionado más arriba pero make se encargará de hacerlas en el orden que le hayamos señalado. Como no he puesto una @ delante de las órdenes, se muestran en pantalla según las va ejecutando:

~$ make
gcc -c main.c
gcc main.o
~$

Veis que hace lo que necesitábamos en la etapa anterior. Además, si volvemos a ejecutar make sin haber editado los archivos nos dirá que no tiene nada que hacer, y es que make comprobará si ha habido cambios en algún archivo  y si no los hay no hará nada. De esta forma evitará tener que hacer trabajo en balde.

También se pueden crear otras reglas para que limpie los archivos generados, para que instale etc. y, por supuesto, las reglas pueden complicarse muchísimo más. Pero con esto por ahora bastante bien.

Espero que os sirva como comienzo a las cosas. Es una entrada poco técnica, no como las que vendrán pronto. Pero hay que tener de todo en esta vida.

Resumen de ideas importantes:

  • Compilar (gcc -c): Crea los objetos (.o o .obj).
  • Linkar: Une los objetos para crear ejecutables. Busca librerías y las añade si es necesario.
  • Make: proceso de automatización de estas cosas.

Y unos enlaces para que profundicéis:

Y esto es todo por hoy.

Un abrazo.


[1] supercremas: de “cremas” y “super”. Cosa muy cremas, muy molona.

[2] estoy resumiendo mucho aquí, pero profundizaré más adelante en otra entrada.

Anuncios

6 pensamientos en “[Intro] Compilación, Linkado y Makefiles en C

  1. Libmatthread: Mi nueva librería y locura matemático-matricial en C – Free Hacks!

  2. CMake en proyectos Qt – Free Hacks!

  3. Software Libre. Sociedad Libre. – Free Hacks!

  4. Lo que he aprendido: makefile para pandoc | Onda Hostil

  5. Makefile para MarkDown y Pandoc – Free Hacks!

  6. Curso no convencional de LaTeX: la opción Pandoc | Onda Hostil

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s