PRIMEROS PASOS CON EL GCC GCC (GNU Compile Colection) es una familia de compiladores creada por la GNU que suporta múltiples lenguajes incluyendo: C, C++, Pascal, Fortran, Objetive C, Java. Indice de la guía Pasos previos Conociendo el compilador Compilación sencilla Usando la opción -o Probando un ejecutable Compilando y enlazando por pasos Pasos previos Como punto de partida, siga los siguientes pasos: 1. Dentro del directorio asociado al usuario, cree una carpeta llamada lab5. Una vez hecho esto ingrese a esta carpeta: 2. Una vez dentro de la carpeta recién creada (verifique que si esta allí con el comando pwd), invoque un editor de texto (si esta en Ubuntu invoque el editor gedit, si esta en Kubuntu invoque el editor kwrite) desde la consola (no olvide colocar al final del nombre del editor el carácter & para que la consola no sea bloqueada): 3. Una vez que se abra el editor copie y pegue el siguiente código fuente: #include <stdio.h> // Declacion de constantes #define PI 3.14 const int N = 3; // Declaracion de variables double area, perimetro, r; int i; int main() { printf("Digite el valor del radio del circulo: "); scanf("%lf",&r); area = PI*r*r; perimetro = 2*PI*r; for(i = 0;i < N;i = i+1) { printf("iteracion %d: area = %lf y perimetro = %lf\n",i,area,perimetro); } return 0; } 4. Guarde el archivo anterior como main.c dentro de la carpeta lab5 recientemente creada. Preguntas Explique de manera breve lo que hace el código anteriormente mostrado. Conociendo el compilador Una vez editado el código fuente, el siguiente paso consiste en realizar la compilación. El compilador GCC es comúnmente invocado usando el comando gcc. Es muy importante conocer la versión del compilador pues muchos programas disponibles para instalar tienen exigencias sobre la versión del compilador. Para conocer la versión del compilador se invoca el comando gcc con la opción --version, asi: También es de particular importancia conocer como invocar la ayuda del compilador gcc, si lo que se quiere es saber cómo primera aproximación es conocer lo que hace el compilador se puede hacer uso de los comandos whatis o apropos tal y como se muestra en la siguiente figura: Ahora bien, si lo que se quiere hacer es conocer la forma de utilizar el compilador, lo más conveniente es invocar su ayuda con la opción --help tal y como se muestra en la siguiente figura: Otra alternativa consiste en invocar el manual del compilador, usando para ello el comando man tal y como se muestra en la siguiente figura: Preguntas Visualice la ayuda del comando gcc en su máquina local, y responda las siguientes preguntas: ¿Cuál es el modo de uso del comando gcc? ¿Qué significan las opciones –E, -S, -c, -o y -v? Compilación sencilla Si observa la sinopsis del comando gcc se puede notar que es necesario pasar el nombre del archivo fuente a compilar, por lo tanto si se invoca el gcc sin pasar argumentos se despliega un mensaje de error como se muestra a continuación. Ahora bien, también suele suceder que pasemos como argumento el nombre de un archivo que no existe, en este caso el compilador desplegara un mensaje de error como el que se muestra a continuación. Ahora, verificando previamente que se encuentra el archivo fuente main.c en el directorio en el que se está actualmente ubicado ejecute el comando gcc pasando como argumento el nombre del archivo tal y como se muestra en la siguiente figura: Como se puede observar en la figura anterior, si no hay errores tras la compilación, usted seguramente habrá notado que aparece un nuevo archivo: a.out. Pues bien, resulta que siempre que se invoca el compilador pasando solo el código fuente (main.c en este caso) como argumento por defecto y sin ninguna opción adicional el resultado es un ejecutable con nombre a.out. Lo anterior nos remite a una primera regla: La manera más sencilla de generar ejecutables con el comando gcc es la que se muestra a continuación: gcc archivo_fuente Donde el archivo fuente (archivo con extensión .c) es un archivo escrito en lenguaje de programación c. El resultado es siempre un ejecutable con nombre a.out Probando un ejecutable Una vez que la compilación ha sido llevada a cabo, solo resta probar el ejecutable y mirar que funcione correctamente. Invoque el ejecutable (a.out) tal y como se muestra a continuación: Note de la figura anterior que para invocar el ejecutable se tiene que anteponer antes de su nombre el carácter punto seguido del carácter slash (./). Preguntas ¿Qué sucede si se invoca el ejecutable anteriormente generado sin usar ./? Uso de la opción -o Si desea crear un archivo de salida con un nombre diferente usted puede usar la opción –o. Así: Como se puede ver el nombre que tendrá el ejecutable será el nombre (ejecutable para el caso anterior) que va después de la opción –o. La ejecución de este nuevo ejecutable se hace como se muestra en la siguiente figura: Preguntas ¿Cómo se debería emplear el comando gcc para generar de un archivo fuente llamado main2.c un ejecutable con nombre miFuckExe? ¿Cómo se invoca el ejecutable anteriormente generado? Examinando el proceso de compilación Antes de proseguir abra un editor de texto y codifique el siguiente código fuente, una vez hecho esto guarde el archivo como main2.c: /* Ejemplo tomado de: Examining the Compilation Process. Part 1 Revista: Linux Journal (http://www.linuxjournal.com) */ #include <stdio.h> // This is a comment. #define STRING "This is a test" #define COUNT (5) int main () { int i; for(i = 0; i < COUNT; i++) { printf(“%s”,STRING); } return 0; } En los casos anteriores, se genero el ejecutable mediante un solo comando pero en realidad, para llegar desde un archivo fuente a un ejecutable se siguen tres pasos (preprocesamiento, compilación y enlazado), tal y como se muestra en la siguiente figura: Programa fuente Preprocesador Programa preprocesador Compilador 00100 Ref? Programa compilado Enlazador 00100 01111 11111 Programa ejecutable Como se puede notar en la figura anterior los pasos para compilar son: Preprocesamiento: Esta es la primera del proceso de compilación y es llevada a cabo por el preprocesador de C el cual es el responsable de 3 tareas particularmente: sustitución de texto, inclusión de archivos y eliminación de comentarios. Para llevar a cabo las dos primeras tareas anteriormente citadas es necesario usar directivas de preprocesador las cuales son las líneas de código que empiezan con el carácter numero (#), más exactamente la directiva #include para la inclusión y #define para la sustitución. Para realizar el preprocesamiento de un archivo se usa la opción –E tal y como se muestra a continuación: Si ejecuta el comando anterior notara que la salida de este será lleva a pantalla por lo que es mejor redireccionarla a un archivo la opción ya bien conocida –o, asi: Como podrá notar el archivo main2.C.C contiene el archivo main2.c ya preprocesador. Ábralo con un editor de texto (por ejemplo: gedit main2..C &) y notara que todas las directivas #include y #define han sido reemplazadas. Compilación: Toma un archivo fuente y genera un archivo objeto. Los archivos objeto son archivos intermedios generados por el compilador antes de crear un ejecutable. El archivo de objeto consiste de una tabla de símbolos y el código C compilado en código de máquina. La tabla de símbolos contiene una lista de funciones y la dirección del archivo objeto en donde se localiza el código para esa función en particular. Todos los compiladores generan los archivos objeto de diferente manera. Para llevar a cabo la etapa de compilación y generar el código objeto se ejecuta el comando gcc con la opción -c, tal y como se muestra a continuación: Como se puede notar el producto resultante de la compilación (main2.o) es un archivo con extensión .o y cuyo nombre para este caso coincide con el nombre sin extensión del archivo fuente (main) Tanto las opciones –c y –o pueden ser usadas simultáneamente, sin embargo en este caso, la salida producida por el comando no será el ejecutable, será el archivo objeto. El nombre del archivo objeto será el que se coloco después de la opción –o; como, La cosa con la opción –o usado en compañía de la opción –c es que permite que yo le pueda poner el nombre que desee al archivo objeto como en el caso anterior en el cual, el archivo objeto resultante quedo bautizado como objeto.o. Enlazado: Es el proceso en el cual se toma el código objeto generado en la etapa de compilación para producir el ejecutable. El encargado de realizar esta operación es el montador o linker. Este es responsable de manipular las llamadas a funciones que se encuentran fuera del archivo de código C que ha sido compilado; busca las referencias a esas funciones en las tablas de símbolos de todos los archivos objeto que están disponibles. Si las referencias son encontradas, se ligan con el código, si no, se genera el error "Undefined Symbol". Con el código objeto, el siguiente paso consiste en enlazar. Asumiendo que el código objeto es main2.o, para enlazar, se usa el comando gcc pasando como argumento el archivo objeto (main2.o) y usando la opción –o para especificar el nombre del ejecutable que será generado, así: El resultado final del enlazado es el archivo ejecutable (myexe para este caso). También es posible invocar el enlazador pasando como argumento de entrada el código objeto, pero sin el uso de la opción –o, esto se muestra a continuación: El resultado de lo anterior es un ejecutable cuyo nombre es el nombre por default, a.out para el caso. Preguntas ¿Cuál sería la invocación del comando gcc para generar un archivo objeto llamado miFuckArchivoObjeto a partir del archivo code.c luego trate de ejecutar dicho archivo. Demuestre lo anterior las correspondientes capturas de pantalla? ¿Es posible ejecutar el archivo objeto anteriormente generado? ¿Cuál sería el comando gcc empleado para que genere un ejecutable ha llamado fuckProgram a partir del archivo objeto miFuckArchivoObjeto previamente generado. ¿Cómo se ejecutaría el comando fuckprogram? Ensamblado Cuando se usa la opción –S, lo que se hace es detener al compilador justo antes del proceso de ensamblaje. La salida es un archivo en el lenguaje ensamblador (con extensión .s) asociado a la maquina. Ejecute el comando anterior. Constate lo anterior con una captura de pantalla. Una vez hecho esto, abra con su editor favorito el archivo code1.s, notara una serie de mnemotécnicos asociados a la maquina. Tabla Resumen La siguiente tabla resume las opciones básicas empleadas para compilar. Una vez llegue acá pregúntele al profesor cada una de lo que estas significan: Opcion -o Significado Permite especificar el resultado de una operación -E Solo realiza la opción de preprocesado -c -Wall Solamente genera código objeto Activa todos los warnings (Advertencias). Se manejan 4 niveles de optimización: 1- 4 (#), donde a mayo numero mayo grado de optimizacion Optimiza el código ejecutable resultante -O# Uso Ejemplo: gcc programa.c –o programa.out El archivo ejecutable recibirá el nombre de programa.out en vez de a.out como sucede por defecto. Ejemplo: gcc -E programa.c –o programa.C La salida es entregada por la salida estándar (stdout) y debe ser redireccionada para lo cual se debe usar –o con el fin de indicar el archivo de salida. Ejemplo: gcc -c programa.c –o programa.o Ejemplo: gcc -Wall -c programa.c –o programa.o Ejemplo: gcc –O4 -c programa.c –o programa.o -g Habilita soporte para debug. Incompatible con opciones de optimización. Ejemplo: gcc –g -c programa.c –o programa.o Actividades adicionales Usando los comandos previamente vistos intente compilar el archivo fuente lab5_p1.c. Identifique y corrija los errores de sintaxis. Modifique el código code1.c de modo que produzca varios errores (falta del punto y coma, variable no declarada), anote en una tabla los mensajes del compilador y al frente la forma de corregirlos. Consulte con el profesor la forma de hacer esto.