GNU cc (gcc) es el compilador del Proyecto GNU. Compila programas escritos en C, C++, Objective C, e incluso fortran (a través de g77). Próximamente estarán disponibles Pascal, Modula-2, Ada 9x y otros muchos más lenguajes de desarrollo.
gcc permite al programador el control total del proceso de compilación, compuesto de cuatro etapas:
Se puede parar el proceso después de cada etapa para ir examinando los resultados. Acepta los dialectos del lenguaje C (ANSI-C y K&R), así como C++ y Objective C. Puede incorporar en el código binario información para el depurado, así como realizar diversas optimizaciones de código. Además es un compilador cruzado, o sea, se puede desarrollar código en un procesador para se ejecutado en otro con distinta arquitectura. Por último, gcc posee extensiones de los lenguajes C y C++ que mejoran la optimización y facilitan el trabajo, a cambio de perder portabilidad (cosa poco recomendable).
Para coger familiaridad, empecemos con el típico ejemplo en C:
1 2 3 4 5 6 7 8 9 10 |
/* * hello.c - Mi primer programa de C */ #include int main(void) { fprintf(stdout, "¡Hola, MISAEL!\n"); return 0; } |
Para compilar y ejecutar este programa:
$ gcc hello.c -o hello
$ ./hello
¡Hola, MISAEL!
La primera orden le dice al gcc que compile y enlace el fichero fuente hello.c, generando el ejecutable indicado por el argumento -o hello. La segunda orden ejecuta el programa, obteniéndose como resultado la tercera línea.
Varias cosas han pasado sin darnos cuenta. Lo primero que ha hecho gcc es manda al preprocesador (cpp) el fichero hello.c para expandir macros e incluir el contenido de los ficheros #included. Seguido, se compila el código preprocesado en código objeto, para finalmente el linkador (ld) crea el hello binario.
Veamos este proceso paso a paso. Si usamos la opción -E paramos el proceso justo después de realizarse la precompilación:
$ gcc -E hello.c -o hello.i
Podemos observar en el fichero hello.i el resultado del preprocesado, con el fichero stdio.h incrustado dentro de él. Continuando con el proceso, usaremos la opción -c para parar despúes de realizar la compilación.
$ gcc -c hello.i -o hello.o
Ya tan sólo queda enlazar el fichero objeto con las librerías del sistema para generar el ejecutable:
$ gcc hello.o -o hello
Para saber el punto de arranqu gcc se fija en la extensión del fichero de entrada.. Las extensiones más comunes reconocidas por gcc son
EXTENSIÓN | TIPO | ||
---|---|---|---|
.c .C .cc .i .ii .S .s .o .a .so |
Código fuente Lenguaje C Código fuente Lenguaje C Código fuente C Preprocesado Código fuente C++ Preprocesado Código fuente Lenguaje Ensamblador Código objeto compilado Código de librería compilado | ||
Aunque lo normal es crear un ejecutable a partir del código fuente, a veces resulta conveniente parar el proceso en un punto determinado. Un caso habitual es cuando queremos obtener el código objeto para integrarlo en una librería, por lo que no es necesario la etapa de enlace. Otro caso cuando queremos obtener el código del precompilado para chequear algún conflicto que tengamos entre los ficheros includes y nuestro código.
La mayor parte de los programas de C se generan partiendo de varios fuentes, códigos objeto y librerías. gcc tomará los ficheros que le damos de entrada, los procesará convenientemente, y los enlaza para generar un único ejecutable. Dar todos y cada uno de los ficheros que componen una aplicación puede resultar demasiado tedioso. Para facilitar esta tarea se suele utilizar la utilidad make que veremos más adelante.
La lista de opciones ocuparía varias páginas, por lo que sólo veremos las opciones más comunes:
Opción | Descripción | ||
---|---|---|---|
-o <file > | Nombre del fichero de salida. Si no se especifica al generar el ejecutable, el nombre por defecto será a.out | ||
-c | Compilar sin enlazar | ||
-DMAC=VAL | Define el macro MAC y le asigna el valor VAL | ||
-IDIR | Sitúa el directorio DIR delante de la lista de directorios dónde buscar los ficheros includes. | ||
-LDIR | Sitúa el directorio DIR delante de la lista de directorios dónde buscar las librerías. | ||
-static | Enlaza con librerías estáticas. Por defecto enlaza las librerías dinámicamente. | ||
-lFICH | Enlaza con la librería libFICH | ||
-g | Incluye información estándar para depurado | ||
-ggdb | Incluye información específica para el depurador gdb | ||
-O | Optimiza el código compilado | ||
-ON | Especifica un nivel de optimación del código entre 0 y 3 | ||
-ansi | Soporta el C ANSI/ISO estándar | ||
-pedantic | Emite todos los avisos requeridos por el C ANSI/ISO | ||
-pedantic-errors | Emite todos los errores requeridos por el C ANSI/ISO | ||
-traditional | Soporta la sintáxis Kernighan & Ritchie del lenguaje C | ||
-w | Suprime todos los mensajes de aviso (una mala idea) | ||
-Wall | Emite todos los avisos que el gcc pueda generar. | ||
-werror | Convierte todos los avisos en errores, lo que parará la compilación | ||
-MM | Crea una lista de dependencias compatible con make | ||
-v | Muestra los comandos utilizados en cada etapa de la compilación | ||