Programación en Linux Programando con GNU/Linux • Compilado y enlazado – A la hora de generar un programa en C se suele pasar por dos fases: – Compilar • Traduce cada archivo de C (*.c) de nuestro programa a lenguaje máquina almacenando la traducción en los archivos de código objeto (*.o). Para ello usamos el GCC (GNU C Compiler) a través del comando gcc – Enlazar • Une todos los archivos de código objeto para fundirlos en el ejecutable de la aplicación. Se usa el comando ld. • Por fortuna para nosotros gcc llama por defecto a ld ahorrándonos tener que realizar los dos pasos a mano. Tomemos el siguiente programa: 2 Programando Linux Programando con GNU/Linux holamundo.c • Y ejecutemos el comando: – $ gcc holamundo.c • Si listásemos el contenido del directorio actual con el comando ls veríamos un nuevo archivo con el nombre de a.out. Ese archivo contiene nuestro programa y puede ser fácilmente ejecutado. – $ ./a.out El que a buen árbol se arrima, buena sombra lo cobija. 3 Programando Linux Programando con GNU/Linux • Con el fin de cambiar el nombre se puede utilizar la opción -o <nombre_ejecutable> • $ gcc -o holamundo holamundo.c • $ ./holamundo El que a buen árbol se arrima, buena sombra lo cobija. 4 Programando Linux Programando con GNU/Linux • Una práctica muy habitual en la programación es dividir nuestro código en varios archivos, cada uno especializado en un tarea determinada. • Para generar nuestro programa sólo debemos listar los archivos que lo forman en la línea de comandos del gcc. • $ gcc -o holamundo main.c holafunc.c • $ ./holamundo El que a buen árbol se arrima, buena sombra lo cobija. 5 Programando Linux Programando con GNU/Linux • Cuando gcc llama a ld no solo se están enlazando a nuestro programa el código objeto de main.c y el de holafunc.c. El compilador sabe que para que nuestro programa funcione es necesario que esté enlazado a una serie de bibliotecas estándar del sistema, así que las incluye automáticamente. Una de esas bibliotecas es la libc cuya documentación podemos obtener con el comando: $ info libc • 6 Programando Linux Programando con GNU/Linux • Funciones como fopen, malloc, printf y en general todas las del C estándar y muchas más se definen en la libc. Evidentemente en nuestro sistema existen bibliotecas para toda clase de tareas cuya documentación se puede obtener recurriendo a la ayuda del sistema. Sin embargo, la mayor parte de esas bibliotecas no se enlazan automáticamente, así que nos queda la duda de como resolver este problema. Por ejemplo vamos a modificar holafunc.c (utilizando una funcion matematica) 7 Programando Linux Programando con GNU/Linux • Si generamos holamundo veremos el siguiente mensaje de error: • $ gcc -o holamundo main.c holafunc3.c – /tmp/ccKSzM6q.o: In function`holafunc': – /tmp/ccKSzM6q.o(.text+0x30): undefined reference to `cos' – collect2: ld returned 1 exit status 8 Programando Linux Programando con GNU/Linux • Ese mensaje nos indica que la función cos() llamada desde holafunc() no está definida puesto que se encuentra en una biblioteca que no está siendo enlazada al programa. Para resolverlo se emplea la opción - l<nombre_biblioteca> con la que se indica la biblioteca adicional que debe ser enlaza al programa. – $ gcc -lm -o holamundo main.c holafunc3.c 9 Programando Linux Programando con GNU/Linux • Al especificar -lm se enlaza la biblioteca libm (como vemos no hace falta poner el lib cuando se indica el nombre de la biblioteca) que contiene la defunción de cos(). Es importante destacar que el enlazador sólo busca bibliotecas en una serie de directorios estándar de nuestro sistema. Por ejemplo libm se encuentra en /usr/lib/ que es un directorio estándar. Si deseamos enlazar bibliotecas situadas en otros directorios, como por ejemplo el directorio actual, debemos usar la opción -L<ruta_biblioteca>. 10 Programando Linux Programando con GNU/Linux • Es evidente que utilizar la línea de comandos resulta molesto incluso cuando se dispone de unos pocos archivos de código fuente. Para ayudar en dichas tareas se utiliza el comando make. Con el objetivo de que funcione es necesario disponer de un archivo de nombre Makefile en el directorio de nuestro código fuente. El archivo debe contener reglas que le indiquen al make como generar la aplicación. 11 Programando Linux Utilidad ‘Make’ 1) 2) 3) 4) 5) Proceso de compilación y montaje Dependencias y regeneración selectiva Makefile Aplicaciones Generación automática de dependencias 12 Programando Linux Compilación y montaje alfa.c alfa.o prog gcc -c alfa.c -o alfa.o beta.c gcc -o prog alfa.o beta.o beta.o gcc -c beta.c -o beta.o 13 Programando Linux Recompilación selectiva * = modificado alfa.c * alfa.o * prog gcc -c alfa.c -o alfa.o beta.c * gcc -o prog alfa.o beta.o beta.o 14 Programando Linux Recompilación selectiva * = modificado alfa.c alfa.o prog beta.c * beta.o * * gcc -o prog alfa.o beta.o gcc -c beta.c -o beta.o 15 Programando Linux Comparación de fechas 15.11 alfa.c 01.12 alfa.o 12.32 12.02 prog 30.12 beta.c 31.12 01.12 gcc -o prog alfa.o beta.o beta.o gcc -c beta.c -o beta.o 16 Programando Linux Dependencias múltiples Ajustar Parrafo Linea Palabra 17 Programando Linux Dependencias múltiples ajustar.cpp ajustar.o ajustar parrafo.h parrafo.cpp parrafo.o linea.h linea.cpp linea.o palabra.h palabra.cpp palabra.o 18 Programando Linux Dependencias múltiples ajustar.cpp ajustar.o ajustar (*) parrafo.h parrafo.cpp parrafo.o linea.h linea.cpp (*) linea.o (*) palabra.h palabra.cpp palabra.o 19 Programando Linux Dependencias múltiples ajustar.cpp Ajustar.o (*) ajustar (*) parrafo.h parrafo.cpp Parrafo.o (*) linea.h (*) linea.cpp Linea.o (*) palabra.h palabra.cpp palabra.o 20 Programando Linux ‘Makefile’ • Dependencias y acciones objetivo: dependencia dependencia ... accion accion . . . objetivo: dependencia ... accion . . . 21 Programando Linux ‘Makefile’ para ajustar ajustar: ajustar.o parrafo.o linea.o palabra.o gcc -o ajustar ajustar.o parrafo.o linea.o \ palabra.o palabra.o: palabra.cpp palabra.h gcc -c palabra.cpp -o palabra.o linea.o: linea.cpp linea.h palabra.h gcc -c linea.cpp -o linea.o . . . 22 Programando Linux Variables y reglas implícitas OBJS = ajustar.o parrafo.o linea.o palabra.o ajustar: $(OBJS) gcc -o ajustar $(OBJS) %.o : %.cpp gcc -c $< -o $@ palabra.o: palabra.cpp palabra.h linea.o: linea.cpp linea.h palabra.h . . . 23 Programando Linux Ejemplo • Las primeras líneas se utilizan para definir variables que serán utilizadas en el resto de nuestro programa. Por ejemplo, definimos en CC el compilador a utilizar, es decir el gcc, mientras que las variables CFLAGS y LFLAGS especifican las opciones para el compilador y el enlazador respectivamente. En nuestro caso indicamos con -lm que queremos enlazar la biblioteca libm, con -g que deseamos incluir el código de depuración en el ejecutable de nuestro programa y con -Wall que el compilador debe avisarnos a la más mínima sospecha de un posible error en el programa. 24 Programando Linux Ejemplo • Por último se listan en OBJECTS el nombre de los archivos de código objeto (*.o) que formarán nuestra aplicación y en INCLUDE los includes (*.h) de nuestro código fuente. Las siguientes líneas del Makefile especifican los targets u objetivos de la ejecución del make: 25 Programando Linux Ejemplo holamundo: $(OBJECTS) $(CC) $(LFLAGS) -o $@ $^ • Indica que el programa holamundo depende de disponer de los archivos de código objeto listados en OBJECTS y que para generarlo debemos enlazarlos con el programa especificado en CC y con las opciones de LFLAGS. Para generar holamundo basta con ejecutar: $ make holamundo • • 26 Programando Linux