Manual de C/C++ en Linux: El compilador GCC
Vamos a ver el proceso de compilación de hello.c, que consta de cuatro pasos. Partimos de un archivo de texto con el código fuente (.c):
$ ls -l hello.c -rw-r--r-- 1 francis francis 102 2007-09-16 13:10 hello.c
- Preprocesado: el preprocesador traduce las llamadas directivas de preprocesador:
quita los comentarios, inserta el contenido de los archivos incluidos con #include y
sustituye por su valor las constantes definidas con #define.
- Comando:
$ gcc -E hello.c > hello.pp
- Salida: código fuente preprocesado (.pp)
$ ls -l hello.pp -rw-r--r-- 1 francis francis 17873 2007-09-16 13:11 hello.pp
- Comando:
- Compilado propiamente dicho: el compilador traduce el código fuente al
ensamblador propio del procesador de nuestra máquina.
- Comando (realiza los pasos 1 y 2):
$ gcc -S hello.c
- Salida: ensamblador (.s)
$ ls -l hello.s -rw-r--r-- 1 francis francis 455 2007-09-16 13:12 hello.s
- Comando (realiza los pasos 1 y 2):
- Ensamblado: el ensamblador crea el código objeto, que es lenguaje máquina
entendible por el procesador.
- Comando (realiza los pasos 1, 2 y 3):
$ gcc -c hello.c
- Salida: código objeto (.o)
$ ls -l hello.o -rw-r--r-- 1 francis francis 884 2007-09-16 13:12 hello.o
- Comando (realiza los pasos 1, 2 y 3):
- Enlazado: aunque el código objeto (.o) es comprensible
para el ordenador (ya que es binario) no puede ser ejecutado porque que no está
enlazado: es necesario combinarlo con las librerías y crear un archivo ejecutable.
Esta tarea es el enlazado y la realiza el enlazador.
- Comando (realiza los pasos 1, 2, 3 y 4):
$ gcc -o hello hello.c
- Salida: código binario (ejecutable)
$ ls -l hello -rwxr-xr-x 1 francis francis 7021 2007-09-16 13:13 hello
El enlazado puede ser dinámico o estático:
- enlazado dinámico: en este caso, las librerías no se insertan
en nuestro programa al compilarlo. Cuando ejecutemos nuestro programa, cada vez que necesite
algo de una librería irá a buscarlo a ésta. Si borramos alguna librería
nuestro programa dará un error de que no la encuentra ya que accede a la librería
en tiempo de ejecución. El ejecutable es más pequeño y se verá
afectado si hacemos cambios en las librerías. Esto es una ventaja si lo que hemos hecho
ha sido corregir un error en la librería pero es un inconveniente si nos obliga a recompilar
el ejecutable (por ejemplo, si hemos añadido un parámetro a una función).
Las librerías dinámicas suelen llamarse libnombre.so (shared object)
y se suelen usar en programas grandes o de sistema. Por defecto el enlazado es dinámico:
$ gcc -o hello hello.c $ ls -l hello -rwxr-xr-x 1 francis francis 7021 2007-09-16 13:13 hello
El comando ldd muestra las librerías dinámicas que usa un ejecutable (en cada línea aparece el nombre de la librería, la ruta completa y dónde está mapeada en el espacio de direcciones virtuales):
$ ldd hello linux-gate.so.1 =>(0xb7f9d000) libc.so.6 =>/lib/tls/i686/cmov/libc.so.6 (0xb7e4f000) /lib/ld-linux.so.2 (0xb7f9e000)
Si ldd muestra como salida not found para alguna librería quiere decir que no la encuentra por lo que el programa no podrá ser ejecutado. Tendremos que buscar la librería y colocarla en el lugar correcto, que por defecto es /lib y /usr/lib.
- enlazado estático: en este caso, las librerías se insertan
en nuestro programa cuando lo compilamos de manera que el ejecutable resultante incluye las
funciones de las librerías y ya no necesita acceder a éstas en tiempo de
ejecución. El ejecutable es más grande pero más rápido, podemos
llevarlo a otro ordenador sin tener que llevar las librerías y no se verá
afectado por cambios en las librerías. Las librerías estáticas suelen
llamarse libnombre.a (archive) y se suelen usar en programas pequeños.
Para que el enlazado sea estático debemos especificar la opción -static (vemos la diferencia de tamaño entre el ejecutable con enlazado estático y el ejecutable con enlazado dinámico):
$ gcc -static -o hello hello.c $ ls -l hello -rwxr-xr-x 1 francis francis 495407 2007-09-16 13:22 hello
Los ejecutables con enlazado estático no dependen de ninguna librería:
$ ldd hello not a dynamic executable - statically linked
El compilador tiene varias opciones que se utilizan en la fase de enlazado:
- -l<nombre_librería>: si el programa emplea alguna
librería diferente de la librería E/S estándar stdio
hay que incluirla en el comando de compilación. Por ejemplo, si se utilizan
funciones matemáticas tendremos que enlazar la librería matemática
math (y no olvidar la sentencia #include <math.h>):
$ gcc -o arch1 arch1.c -lmath
- -L<ruta_librería>: añade un directorio a la lista
de directorios donde el compilador busca librerías (por defecto /lib
y /usr/lib):
$ gcc -o arch1 arch1.c -L/home/francis/lib milib.a
- -I<ruta_header>: añade un directorio a la lista de directorios
donde el compilador busca archivos de cabecera #include (por defecto /usr/include):
$ gcc -o arch1 arch1.c -I/home/francis/include
- Comando (realiza los pasos 1, 2, 3 y 4):
Deja un comentario