Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
alumno
o el correspondiente identicador que nos hayan asignado, obtendremos en la pantalla la res-
puesta del proceso login de la gura 2.2, que consiste en una nueva peticin para que nosotros
escribamos una palabra clave (password) que permita al proceso login conrmar que somos quien
decimos ser (autenticacin). En nuestro caso escribiremos de nuevo
alumno
o la password que corresponda a nuestro login. El proceso login no escribe la password en
pantalla, ni caracteres de mscara que permitan siquiera contar los caracteres de la password.
Si la validacin resulta correcta obtendremos el resultado que se observa en la gura 2.3
2.1. Comienzo y terminacin de sesin (login, exit, shutdown) 7
Figura 2.2: Inicio de sesin
Figura 2.3: Sesin iniciada
8 2.1. Comienzo y terminacin de sesin (login, exit, shutdown)
Ahora, el proceso login ha creado un proceso shell, (abreviadamente un shell) que ser el
que se ocupe de que se ejecuten nuestras rdenes. No obstante, el shell es un intrprete que,
generalmente, no ejecuta por s mismo nuestras rdenes, sino que, despus de analizarlas, pone
en marcha programas especcos para ejecutar las diferentes rdenes.
A la secuencia de operaciones realizada hasta aqu se denomina en UNIX abrir una sesin.
Cuando hayamos terminado de trabajar con el terminal, debemos dar por terminada la
sesin, escribiendo
e xi t
lo cual nos llevar a la situacin de la gura 2.1. Nuestro shell ha terminado y se ha puesto
nuevamente el terminal bajo el control de un proceso login para permitir iniciar una nueva
sesin al mismo usuario o a otro.
No es necesario cerrar una sesin que tengamos abierta en un terminal para poder abrir
otra en otro terminal que tengamos inactivo. Por ejemplo, aqu, antes de cerrar la sesin en
tty2 podramos haber usado el terminal tty1 (pulsando <Alt>-F1) y abrir en l una nueva
sesin (del mismo modo que lo hemos hecho en el ejemplo previo). Si luego hubiramos vuelto
a pulsar <Alt>-F2 habramos obtenido de nuevo la pantalla del terminal tty2 tal como la
tuviramos cuando cambiamos de terminal. Esto nos permite trabajar hasta con seis sesiones
abiertas simultneamente.
El proceso de cerrar una sesin del shell no termina la ejecucin del sistema operativo. Si que-
remos dar de baja el sistema, por ejemplo porque tenemos que apagar la mquina, teclearemos
desde una sesin abierta como administrador del sistema (root)
shutdown h 0
lo cual cerrar todas las sesiones abiertas y dar de baja ordenadamente el sistema.
Resumiendo lo que hemos visto hasta aqu, el administrador del sistema, al darnos de alta
como usuarios (o, como se dice habitualmente, al abrirnos una cuenta), debe asignarnos un login
y una password que nos servirn para poder abrir sesiones en ese sistema UNIX.
Adems en UNIX hay diferentes programas de tipo shell, de modo que el administrador
tambin debe asignarnos, entre otras cosas que ya iremos precisando a lo largo de los captulos
siguientes, el programa shell que se usar por defecto para ejecutar nuestras rdenes cuando
abramos una sesin.
En estas lecciones se supondr siempre que el programa shell usado ser el shell bash. La
informacin de referencia para este shell puede ser consultada en [2], y es recomendable disponer
de la informacin de [4] como ayuda habitual.
Otros tipos de shell ejecutan las rdenes esencialmente de la misma manera que el shell bash,
pero dieren de ste en su forma de programacin.
2.2. Escritura de rdenes en UNIX 9
2.2. Escritura de rdenes en UNIX
2.2.1. Formato de las rdenes
Las rdenes que podemos escribir en el terminal, una vez que tengamos abierta una sesin,
pueden ser de muchas clases, pero su formato bsico es muy parecido en los distintos casos.
Una orden comienza por una palabra que identica la clase de operacin que debe hacerse y
que es denominada nombre de la orden. Es comn en la bibliografa denominar comando tanto
a la orden completa como a su nombre.
Despus, y separadas por uno o ms espacios del nombre de la orden, continan opcional-
mente uno o varios grupos de letras y/o cifras separados entre s por espacios y precedidos
habitualmente cada uno por un signo menos. Estos caracteres especican opciones que deben
ser tenidas en cuenta por el shell para la ejecucin de la orden.
Por ltimo y tambin opcionalmente y separados entre s y de las opciones por uno o ms
espacios, se encuentran series de caracteres que forman los objetivos de la orden. Habitualmente
son nombres de archivos y/o directorios sobre los que la orden debe operar.
En general, el aspecto de la orden sera
<nombre>[<opcin-1>]...[<opcin-m>] [<objetivo-1>]...[<objetivo-n>]
Un ejemplo de una orden tpica sera
c al m 6 2007
El nombre de la orden es aqu cal, las opciones se reducen a -m, mientras que los objetivos
de la orden son 6 2007.
Al escribir las rdenes debemos tener en cuenta que las letras maysculas y las minsculas
no son equivalentes.
Por otra parte, debemos recordar que una orden slo se ejecuta cuando pulsamos la tecla
<RET>, y que mientras no lo hagamos, podemos corregir los errores que hayamos cometido
al escribir. Una vez que pulsamos <RET>, el sistema intentar ejecutar la orden tal como est
escrita, y nos proporcionar la salida correspondiente.
En la gura 2.4 podemos ver la salida de la orden anterior, en la que el sistema nos propor-
ciona un calendario de Junio de 2007.
En cambio si escribimos
CAl m 6 2007
obtendremos la salida de la gura 2.5 en la que observamos el informe de error que nos indica
que la orden CAl no existe. El nombre correcto de la orden es cal.
En ambos casos, el shell queda disponible para que escribamos una nueva orden.
10 2.2. Escritura de rdenes en UNIX
Figura 2.4: Ejemplo de salida de una orden
Figura 2.5: Ejemplo de salida de una orden errnea
2.2. Escritura de rdenes en UNIX 11
Figura 2.6: Ejemplo de salida de la orden cal sin opciones
2.2.2. Efecto de las opciones
Veamos ahora cmo funcionan las opciones. La opcin -m indica que queremos que el ca-
lendario est ordenado de forma que en la primera columna del mes aparezcan las fechas de los
lunes. Si no usamos esa opcin, UNIX ordena el calendario de forma que en la primera columna
del mes aparezcan las fechas de los domingos, como es habitual en los pases anglosajones.
Si escribimos
c al 6 2007
obtendremos la salida indicada en la gura 2.6
2.2.3. Problemas de paginacin (more, less)
Hasta ahora las salidas de las rdenes que hemos obtenido tenan pocas lneas. Cuando la
salida tiene ms lneas de las que caben en una pantalla se plantea el problema de poder leer las
lneas a las que el scrolling ha hecho salir de la pantalla. Como ejemplo podemos ver la salida
de la orden
c al m 2007
tendramos la salida que se observa en la gura 2.7. En ella se observa que las las de texto
correspondientes a los primeros meses del ao 2007 no pueden leerse porque han salido por
12 2.3. Informacin de ayuda sobre las rdenes UNIX (man)
Figura 2.7: Calendario del ao 2007 no paginado
encima de la pantalla. De una salida que presente ese problema se dice que est no paginada,
es decir, que es necesario someterla a un proceso para partirla en pginas con objeto de poder
verla entera.
La forma de resolver este problema es enviar la salida de la orden cal a otra orden que sea
capaz de procesar una entrada sin paginar para producir una salida paginada. Una orden de ese
tipo recibe el nombre de paginador. En UNIX existen diferentes paginadores. Dos de los ms
comunes son more y less.
La forma de enviar la salida de una orden (en este caso cal) para ser usada como entrada
de otra (en este caso more) es usar el operador | (llamado operador pipe).
Si escribimos
c al m 2007 | more
obtendremos como salida la de la gura 2.8.
Ahora debemos ver la pgina siguiente pulsando la barra espaciadora. La pantalla tomar el
aspecto de la gura 2.9.
Podemos observar que la salida de la orden cal se ha completado porque el shell est espe-
rando (ha escrito ya el indicador alumno@ssoo:$)
2.3. Informacin de ayuda sobre las rdenes UNIX (man)
Las preguntas que nos hacemos ahora son
2.3. Informacin de ayuda sobre las rdenes UNIX (man) 13
Figura 2.8: Calendario del ao 2007. Pgina 1
Figura 2.9: Calendario del ao 2007. Pgina 2
14 2.3. Informacin de ayuda sobre las rdenes UNIX (man)
Cuntas y cules son las rdenes que podemos manejar con el shell?
Para una determinada orden cuntas y cules son las opciones disponibles, y cules son
el cometido de la orden y la salida que produce?
En el primer caso no hay una respuesta denida porque eso depende del tipo de UNIX, y,
dentro de un tipo determinado, de la conguracin de la instalacin en la que trabajemos. Ade-
ms, cualquier shell UNIX permite que el programador construya rdenes que el shell ejecutar
sin hacer ninguna diferencia con las que se entregan con el propio sistema. En todo caso se puede
responder que las rdenes bsicas son aproximadamente un centenar. En cuanto a cules son,
en estas pginas estudiaremos las ms importantes.
La respuesta a la segunda cuestin es ms sencilla. Existe en UNIX una orden que permite
al usuario obtener informacin de manual sobre cualquier orden, incluida ella misma. Esa orden
es man.
Cuando el usuario desea obtener informacin de manual sobre una determinada orden, debe
ejecutar una orden man con un objetivo que ser el nombre de la orden sobre la que se desea
obtener informacin.
Por ejemplo, si deseamos saber para qu sirve, cual es el formato o cules son las opciones
de la orden cal podemos escribir
man c al
y obtendremos una salida (paginada) que puede recorrerse hacia adelante o hacia atrs mediante
las teclas de movimiento habituales y cuya primera pgina est representada en la gura 2.10
Como la orden man produce una salida paginada y, al igual que otros paginadores, permite
avanzar y retroceder por ella, el shell debe ser avisado por el usuario de que ya ha terminado de
trabajar con esa salida. Para ello, el usuario debe pulsar la tecla q. Como respuesta, el shell
terminar la ejecucin de la orden man y escribir de nuevo el indicador del shell para informar
al usuario de que est esperando una nueva orden.
Naturalmente se puede obtener informacin de manual sobre la orden man escribiendo
man man
El formato de la orden man es
pwd
Para cambiar el directorio de trabajo actual se usa
cd . .
hara que nuestro nuevo directorio de trabajo actual fuese /home. Se ha citado el directorio
padre mediante un path relativo. El nombre completo del directorio que tomar la orden ser
entonces /home/alumno/..; comprubese usando la orden pwd.
En cualquier momento podemos hacer que nuestro directorio home vuelva a ser nuestro
directorio de trabajo actual mediante la orden cd sin argumentos.
cd
3.2. El shell y los metacaracteres
Como veremos en todo lo que sigue, muchos de los objetivos de las rdenes del shell son
nombres de archivos o directorios, y en la misma orden puede haber varios de estos objetivos.
Una forma de simplicar la escritura de las rdenes consiste en usar ciertos caracteres (me-
tacaracteres o caracteres comodn) para que el shell los interprete de modo especial, y ello le
permita generar diversos nombres objetivo a partir de ciertos patrones que escribimos en la lnea
de rdenes. As pues, una palabra que contenga estos caracteres se sustituye por una lista con
los nombres de archivo o de directorio que se ajusten al patrn.
Los metacaracteres ms usados son
3.3. El editor de texto joe 19
* Representa cualquier cadena (incluida la cadena vaca). El carcter . no es generado en las
sustituciones de * cuando est en la primera posicin del nombre
? Representa cualquier carcter
[<lista>] Representa cualquier carcter incluido en <lista>. En la lista se pueden poner ca-
racteres o bien intervalos con el comienzo y el nal separados por un signo menos
[!<lista>] Representa cualquier carcter que no pertenezca a <lista>.
3.3. El editor de texto joe
Hay muchas maneras de crear archivos durante una sesin de trabajo, pero una de las ms
frecuentes es utilizar un editor de texto para hacerlo.
En nuestro trabajo utilizaremos habitualmente el editor joe para esa tarea. joe es un editor
adecuado para usar en un terminal alfanumrico. Se trata de un editor de pantalla completa de
tipo WordStar.
La orden para la creacin de un archivo nuevo o bien para la edicin de uno ya existente es
j oe <nombredearchi vo>
El nombre de archivo es necesario slo si se va a editar un archivo existente. Si se trata de
un archivo nuevo, se puede no asignarle nombre hasta el momento de guardarlo.
En la gura 3.1 podemos ver la pantalla de trabajo de joe con una lnea de ayuda en la
parte superior y una lnea de estado en la inferior.
En la zona central el usuario puede escribir el texto del archivo en la forma usual.
joe es un editor con un interfaz unimodal, que admite multitud de rdenes mientras se
escribe el texto. Todas esas rdenes se dan mediante combinaciones especiales de teclas, pero
no es necesario recordarlas todas para trabajar de forma til desde el principio. Si se observa la
lnea de ayuda de la gura 3.1 podemos ver que se puede obtener ayuda mediante la pulsacin
de las teclas <Ctrl>-K-H.
El efecto puede verse en la gura 3.2
En ella podemos observar el panel de ayuda con una serie de combinaciones de teclas para
realizar diversas funciones agrupadas por categoras. Existen varios paneles de ayuda suplemen-
tarios. Pueden verse pulsando repetidamente la combinacin de teclas <Esc> . como puede
observarse en la lnea superior de la pantalla; para volver hacia atrs por la serie de paneles de
ayuda, la combinacin de teclas es <Esc> ,.
La notacin usada en los paneles de ayuda usa el smbolo para indicar la pulsacin de la
tecla <Ctrl>. As por ejemplo, en el grupo de comandos EXIT, puede verse que si necesitamos
salir del editor guardando el archivo que estamos editando, debemos usar KX, lo que signica
que debemos mantener pulsada la tecla <Ctrl> mientras pulsamos sucesivamente las teclas
K y X.
20 3.3. El editor de texto joe
Figura 3.1: Pantalla inicial de joe para un archivo sin nombre y vaco
Figura 3.2: Pantalla inicial de joe con el panel de ayuda visible
3.4. Operaciones bsicas en el sistema de archivos 21
Al pulsar la combinacin de teclas que activa un comando puede que obtengamos ms pe-
ticiones de informacin en la lnea de estado. Por ejemplo, en el caso anterior, si el archivo no
tena nombre, se nos pedir que tecleemos el nombre que deseemos asignarle.
Al menos en la etapa inicial, hasta acostumbrarse al uso de joe, se recomienda mantener en
la pantalla del terminal la informacin de ayuda mientras se edita un archivo.
3.4. Operaciones bsicas en el sistema de archivos
3.4.1. Creacin y eliminacin de archivos y directorios (rm, mkdir,
rmdir)
La creacin de archivos y directorios requiere que el usuario tenga los permisos necesarios, de
modo que un usuario no puede crear, borrar o mover archivos o directorios a cualquier posicin
en la jerarqua del sistema de archivos. Discutiremos este problema en la seccin 3.5. Por el
momento supondremos que todas nuestras operaciones tienen lugar en la parte de la jerarqua
del sistema de archivos que desciende de nuestro directorio home.
Ya hemos visto en la seccin 3.3 una de las formas ms comunes de crear archivos (mediante
un editor de texto), pero los archivos a veces tambin necesitan ser borrados.
Para eliminar archivos, la orden del shell es rm. Su formato es
<orden_1> | <orden_2> | . . .
36 4.4. Creacin de shells hijos (sh)
Por ejemplo
l s al | wc l
escribir en la salida estndar el nmero de lneas del informe que producira la orden ls.
El operador | se llama operador pipe. Se pueden agrupar pipes de la misma forma que las
rdenes simples.
4.3.1. Ejecucin en segundo plano
Hasta ahora hemos ejecutado rdenes de modo que hay que esperar a que termine la ejecucin
de la orden antes de que el shell nos permita escribir y pedir la ejecucin de otra.
Esa forma de trabajar se denomina ejecucin en primer plano.
A veces, sin embargo, nos interesa poder ejecutar una orden, y, sin esperar a que termine,
pedir al shell que ejecute otra. Para ello, la primera orden debe ser seguida del operador &, lo
que indicar al shell que deseamos ejecutarla en segundo plano, concurrentemente (UNIX es un
sistema multiprogramado) con otras que escribiremos luego.
Cuando hacemos eso, el shell imprime un nmero que es el identicador de proceso de la
orden en segundo plano y vuelve inmediatamente a escribir el prompt para permitirnos escribir
nuevas rdenes (que pueden ejecutarse en primer plano o tambin, si queremos, en segundo
plano).
Es corriente redirigir los descriptores de la entrada, la salida y la salida de error estndares
de las rdenes que se ejecutan en segundo plano para evitar que lean o escriban en los mismos
dispositivos que estemos usando para las rdenes que ejecutemos en primer plano.
Por ejemplo, si escribimos
_
`
sh
La orden sh crea un nuevo proceso que ejecuta otro shell, sobre el que podremos ejecutar
rdenes o macros del shell y del que podremos salir al terminar mediante la orden exit como
habitualmente.
Captulo 5
Otras rdenes tiles
5.1. Bsqueda de informacin en el sistema de archivos
Dada la gran cantidad de informacin que est almacenada habitualmente en cualquier
sistema de archivos, uno de los problemas ms frecuentes que se plantea al usuario del sistema
es localizar los archivos que le interesan.
Distinguiremos dos tipos genricos de bsquedas: aquellas en las que se intenta localizar
el o los archivos que nos interesan a partir de condiciones sobre su nombre u otros atributos
y aquellas otras en las que queremos localizar las lneas de los archivos que contienen (en su
interior) determinadas cadenas de caracteres.
5.1.1. Bsqueda de archivos por sus atributos (nd, locate)
La orden nd
La orden nd se usa para localizar archivos particulares y posiblemente ejecutar algn tipo
de accin sobre ellos. Esta orden busca, explorando recursivamente uno o varios directorios,
los nodos que cumplan las condiciones expresadas en la orden y les aplica las acciones que se
indiquen.
A lo largo de la ejecucin de la orden nd, se va tratando cada nodo de los directorios
afectados (nodo objetivo) de modo que se comprueba si se cumplen las condiciones expresadas
para aplicar o no las acciones correspondientes.
En GNU, el formato de la orden es
f i nd / et c s i z e +20 pr i nt
busca los archivos de un tamao mayor de 20 bloques de 512 bytes por debajo del directorio
/etc e imprime sus nombres completos.
l o c at e u [o <nombrebasedatos >]
s or t +2 3
ordenar la entrada estndar usando como clave los caracteres del tercer campo de cada lnea.
Pueden especicarse varias claves de ordenacin. En ese caso la ordenacin tiene lugar por la
primera clave que aparezca en la lnea de rdenes, y, para las lneas en las que esa clave resulte
igual, se realizar una ordenacin por la siguiente clave, etc.
5.2.4. Sumas de comprobacin en archivos (md5sum)
La orden md5sum permite generar una suma MD5 (128 bits) tal como se describe en la
RFC 1321 para cada uno de los archivos cuyo nombre aparezca en la lnea de rdenes. Si no se
da ningn nombre de archivo o se usa el carcter - se lee de la entrada estndar.
La orden se utiliza para comparar los contenidos de uno o ms archivos, puesto que dos
archivos de contenidos diferentes tendrn sumas de comprobacin MD5 diferentes. El formato
de la orden es el siguiente
f r e e [ opci ones ]
Para ms informacin vase la pgina de manual de free.
5.3.4. Determinacin de la actividad de los usuarios (w)
La orden w permite obtener informacin sobre qu usuarios estn conectados al sistema y
lo que estn haciendo. Su formato es
ps [ opci ones ]
Por defecto, ps selecciona todos los procesos que tienen el mismo usuario efectivo que el
usuario en curso y estn asociados al mismo terminal. La informacin proporcionada es el
identicador del proceso, el terminal asociado, el tiempo de CPU consumido y el nombre del
ejecutable. Las opciones ms importantes son
-a Seleccionar todos los procesos salvo los lderes de sesin y los no asociados con un terminal
-e Seleccionar todos los procesos. Se puede escribir -A con el mismo efecto
-f Imprimir informacin detallada sobre los procesos que interesen
-l Imprimir la informacin en formato largo
6.2. Control de trabajos (jobs, fg, bg, kill)
Las rdenes de control de trabajos del shell son habitualmente comandos internos, que per-
miten controlar los trabajos que estn activos en una determinada sesin: terminar determinado
49
50 6.2. Control de trabajos (jobs, fg, bg, kill)
trabajo (matarlo), suspenderlo (pararlo), reanudar un trabajo suspendido o cambiar su modo
de ejecucin.
En UNIX existen dos modos de ejecucin para cualquier proceso: el modo de ejecucin en
primer plano (foreground) y el modo de ejecucin en segundo plano (background).
En cada momento slo puede haber un proceso en primer plano, y ste proceso es el que
utiliza el teclado del terminal.
La forma de obtener informacin sobre los procesos dependientes del shell con indicacin del
nmero de trabajo, el estado en que se encuentra (ejecutando en segundo plano o suspendido)
y el nombre del ejecutable, es utilizar el comando jobs. Su formato es
j obs
Para suspender el proceso en primer plano y pasarlo al segundo plano se utiliza la combina-
cin de teclas <Ctrl>-Z. El proceso que queda en primer plano es el shell.
Un trabajo suspendido puede reanudarse de dos maneras.
Si un trabajo suspendido desea reanudarse de modo que siga ejecutndose en segundo plano
el comando a usar es bg. Su formato es
s l e e p <tiempo>[<s uf i j o >]
donde <tiempo> indica la cantidad de tiempo que se desea esperar. <sujo> permite cambiar
las unidades de <tiempo>. Se puede usar el sujo m para indicar minutos, el sujo h para
indicar horas y el sujo d para indicar das.
6.3.2. No eliminar un proceso al cerrar la sesin (nohup)
La orden nohup permite que la orden del shell que le siga inmediatamente sea ejecutada
de modo que no se elimine el proceso correspondiente aunque se cierre la sesin del shell. Su
formato es
k i l l l [<seal >]
imprime por defecto una lista con los nombres de las seales disponibles en el sistema (no todos
los sistemas UNIX usan las mismas) y sus respectivos nmeros de seal. Si se indica un nombre
de seal, esta forma proporcionar el nmero correspondiente y viceversa.
Parte II
Uso del compilador C de GNU
53
Captulo 7
Introduccin
El desarrollo prctico de la actividad de programacin con un lenguaje compilado como C,
cuando la formacin previa de programacin se ha desarrollado utilizando un lenguaje inter-
pretado como Java, Python, etc., presenta al alumno un problema aadido al del dominio del
correspondiente lenguaje. En la nueva situacin se necesita manejar una herramienta de desarro-
llo que permita controlar las distintas fases que nos conducen a obtener un programa ejecutable
a partir de los archivos correspondientes escritos en lenguaje fuente.
El proyecto GNU de software libre dispone de un gestor de compilacin para los lenguajes
C y C++, denominado gcc, que puede ocuparse de las diferentes fases del proceso de creacin
de un ejecutable (preproceso, compilacin, ensamblaje, enlace).
En lo que sigue, como es habitual, nos referiremos a gcc como el compilador C de GNU,
aunque la herramienta no realiza slo la tarea de compilacin estrictamente considerada.
7.1. Obtencin de un ejecutable a partir de los archivos
fuente
La obtencin de un ejecutable a partir de archivos fuente conlleva la realizacin de varias
fases en secuencia
1. Preproceso
2. Compilacin
3. Ensamblaje
4. Enlace
La herramienta gcc permite desarrollar esas tareas desde cualquier fase y detenerlas en el
punto que nos interese.
Por defecto, gcc supone que los archivos fuente tienen nombre que utilizan una extensin
c o bien una extensin h. stos ltimos son denominados archivos de cabecera, por lo cual
usaremos la denominacin de archivos fuente slo para los primeros.
55
56 7.1. Obtencin de un ejecutable a partir de los archivos fuente
Figura 7.1: Operacin de preproceso
7.1.1. Preproceso
En esta fase, se realizan sobre cada archivo fuente determinadas operaciones de inclusin de
texto procedente de distintos archivos de cabecera, sustitucin y desarrollo de macros y seleccin
condicional de texto de programa para ser compilado posteriormente.
A partir de un archivo fuente, se obtiene as un archivo preprocesado (unidad de compilacin)
que, ms tarde, ser procesado por el compilador (ver g. 7.1).
7.1.2. Compilacin
Durante esta fase, los compiladores puros producen cdigo objeto para la plataforma hard-
ware sobre la que trabajan, adecuado a la arquitectura de sta y al sistema operativo que ms
tarde tendr que dar soporte a la ejecucin de la aplicacin.
No obstante, la herramienta gcc es una herramienta multiplataforma, y hace ese trabajo
en dos partes. En la fase de compilacin, gcc produce cdigo ensamblador para la plataforma
deseada y ms tarde, el cdigo objeto se obtiene mediante el ensamblaje correspondiente.
En la g. 7.2 se representa la operacin de gcc en la fase de compilacin.
7.1. Obtencin de un ejecutable a partir de los archivos fuente 57
Figura 7.2: Operacin de compilacin
Figura 7.3: Operacin de ensamblaje
7.1.3. Ensamblaje
La herramienta gcc produce un mdulo objeto a partir de cada mdulo ensamblador obtenido
en la fase de compilacin (ver g. 7.3).
7.1.4. Enlace
La fase de enlace realiza la tarea de reunir los distintos mdulos objeto obtenidos de las fases
anteriores y los que se deban extraer de las bibliotecas disponibles en un programa ejecutable
(ver g. 7.4).
Despus de que se han desarrollado estas fases hasta el nal, se dispone de un archivo que
puede ser ejecutado sin la presencia de los archivos fuente, sino solamente con el soporte del
sistema operativo (supuesto que no se usan bibliotecas de enlace dinmico). En otras palabras,
los archivos fuente no son ya necesarios para ejecutar el programa.
No obstante, mientras una aplicacin se encuentra en fase de desarrollo, la correccin de los
errores de programacin que causan mal funcionamiento del ejecutable, requiere generalmente
el uso de una nueva herramienta, denominada depurador, que necesita habitualmente referirse al
cdigo fuente para permitir al programador una traza de la operacin del programa en ejecucin.
As pues, el cdigo fuente deja de ser necesario slo cuando la aplicacin se encuentra en fase
de explotacin.
58 7.1. Obtencin de un ejecutable a partir de los archivos fuente
Figura 7.4: Operacin de enlace
Captulo 8
El compilador C de GNU
8.1. Uso de gcc mediante el shell UNIX
La herramienta gcc puede ejecutarse desde el shell UNIX para realizar todas o algunas de
las fases de creacin de un ejecutable a partir de los archivos fuente que han sido descritas en el
captulo 7.
La orden del shell para desarrollar este trabajo, en una forma simplicada, tiene el formato
siguiente
_
`
s e t ar gs [<argumento> . . . ]
donde la lista de argumentos es la que deseemos pasar luego al programa en depuracin (excluido
el nombre del programa).
En nuestro caso utilizaremos los mismos que causaban los errores observados en la gura
9.3.
br main
con lo que obtendremos en el terminal el resultado indicado en la gura 10.3.
En ella podemos observar que nuestro punto de ruptura se encuentra situado en la lnea 10
del archivo ejemplo-gdb1.c.
10.1.3. Ejecucin del programa
Ahora debemos ordenar al depurador que ejecute el programa con las condiciones anterior-
mente establecidas. Para ello se utiliza la orden run. Su formato es el siguiente
run [<argumento> . . . ]
10.1. Una sesin de depuracin con gdb 75
Figura 10.4: Ejecucin hasta el punto de ruptura
En la lista de argumentos se pueden pasar los argumentos de la lnea de rdenes con los
que se desee ejecutar el programa si no se han especicado antes mediante set args (vase
la seccin 10.1.1). Al igual que con set args, en esos argumentos no se especica de nuevo el
nombre del ejecutable.
En nuestro caso ejecutaremos
run
La respuesta del depurador es la que se observa en la gura 10.4. Como puede verse, la
ejecucin se ha detenido antes de ejecutar la primera sentencia de la funcin main, que se
encuentra en la lnea 10 del archivo fuente. En adelante nos referiremos a las sentencias por su
nmero de lnea.
Desde ahora, las rdenes al depurador controlarn la ejecucin del programa. Tpicamente
necesitaramos ahora ejecutar la sentencia nmero 10. La ejecucin de la sentencia inmediata
cuando el programa est detenido se logra mediante la orden n
n
lo cual, en nuestro caso produce el resultado que se observa en la gura 10.5, donde podemos ver
que se ha enviado la cadena de caracteres Las opciones son: al stream de salida estndar
(no se ha escrito en una lnea del terminal porque, en el actual modo de trabajo de ste, no se
escribir nada en l mientras no se complete la lnea, es decir, mientras no se escriba un carcter
de nueva lnea).
76 10.1. Una sesin de depuracin con gdb
Figura 10.5: Ejecucin de la sentencia 10
Adems observamos que la sentencia inmediata que ser ejecutada (la nmero 11) es la
cabecera del bucle while que tiene por objeto obtener de la lnea de rdenes todas los argumentos
que sean opciones (todos los que comienzan por el carcter - hasta el primero que no comience
por dicho carcter exclusive).
Para ejecutar la sentencia 11 podemos usar de nuevo la orden n como antes o bien pulsar
<RET>, lo cual podr ser utilizado en cualquier momento para repetir la ltima orden emitida.
Nuestro resultado puede verse en la gura 10.6.
Lo que observamos es que la siguiente sentencia a ejecutar (la 14) est ya fuera del bucle
de obtencin de las opciones. Cuando la ejecutemos se escribir la lnea correspondiente en el
terminal, con el rtulo de la sentencia 10 seguido del carcter de nueva lnea, puesto que no
se ha encontrado ninguna opcin. Por otra parte, la siguiente sentencia a ejecutar ser la 16.
Efectivamente, eso es lo que observamos en la gura 10.7.
Es evidente el mal comportamiento del programa. Con nuestros argumentos en la lnea de
rdenes hay varias opciones que no han sido localizadas por el bucle while de la lnea 11, que,
en consecuencia, est programado incorrectamente. No se ha ejecutado el cuerpo del bucle ni
una sola vez, as que el problema est en la expresin de control del bucle. En ella se usa un
operador and lgico, en el que el primer operando lleva la cuenta de argumentos procesados en
la lnea de rdenes, en la que se empieza descontando el primero para no tener en cuenta el
nombre del programa y resultar falsa cuando se acaben los argumentos de la lnea de rdenes.
Esa condicin parcial es correcta.
El otro operando intenta determinar si el primer carcter del argumento correspondiente de
la lnea de rdenes es un signo -. Si es as, se trata de una opcin, que se enviar a la salida
estndar y se iterar de nuevo mientras en los nuevos argumentos el primer carcter siga siendo
un signo -.
10.1. Una sesin de depuracin con gdb 77
Figura 10.6: Ejecucin de la sentencia 11
Figura 10.7: Ejecucin de la sentencia 14
78 10.1. Una sesin de depuracin con gdb
Figura 10.8: Orden de salida del depurador
Sin embargo la expresin *++argv[0] no tiene el valor del primer carcter del argumento
de la lnea de rdenes en cada caso. En efecto: inicialmente argv[0] es un puntero al primer
carcter del primer argumento de la lnea de rdenes (el nombre del programa). ++argv[0]
es un puntero al segundo carcter de ese argumento, no al primer carcter del segundo
argumento, que es lo que necesitamos, as que *++argv[0] es el segundo carcter del nom-
bre del programa, que en nuestro caso es un carcter h (el nombre de nuestro programa es
/home/alumno/gdb-ejemplo/ejemplo-gdb1).
Ahora debemos corregir ese error. La expresin correcta es (*++argv)[0], la cual incrementa
argv para apuntar al siguiente argumento de la lnea de rdenes (inicialmente el segundo) y toma
el valor del primer carcter. Para ello debemos salir del depurador mediante la orden q.
q
La salida es la observada en la gura 10.8, en la que el depurador pide conrmacin, puesto
que el programa sigue en ejecucin y posteriormente, termina y el shell normal vuelve a tomar
el control.
Ahora debemos modicar el cdigo fuente en la lnea 11, volver a generar el ejecutable y
ejecutar de nuevo para ver si nuestro problema se ha solucionado. La nueva versin del cdigo
puede verse en el listado 10.1.
El resultado de la generacin del nuevo ejecutable y la ejecucin con nuestros datos puede
verse en la gura 10.9.
Como puede observarse, no hay errores de compilacin ni enlace pero la salida de la versin
2 sigue siendo incorrecta. Las opciones no se capturan bien y al listar el resto de los argumentos
se produce una excepcin de memoria.
10.1. Una sesin de depuracin con gdb 79
1
#include <s t di o . h>
3 #include <s t r i ng . h>
5 void Pr i nt I nf orme ( const char cadena ) ;
7 i nt main( i nt argc , char argv [ ] )
{
9
pr i nt f ( "Las opciones son: " ) ;
11 while(argc > 0 && (++argv ) [ 0 ] == -)
pr i nt f ( " %s " , ++argv ) ;
13
pr i nt f ( "\n" ) ;
15
pr i nt f ( "Otros argumentos de la linea de ordenes\n" ) ;
17 while ( argv++){
Pri nt I nf orme ( argv ) ;
19 argv++;
}
21
return 0;
23 }
25 void Pr i nt I nf orme ( const char cadena )
{
27 i nt l ongi t ud ;
29 l ongi t ud = s t r l e n ( cadena ) ;
pr i nt f ( " %s\tlongitud= %d\n" , cadena , l ongi t ud ) ;
31
return ;
33 }
Listado 10.1: Programa ejemplo. Versin 2
80 10.1. Una sesin de depuracin con gdb
Figura 10.9: Salida de la versin 2
En la gura 10.10 podemos ver la situacin de partida para seguir la traza de ejecucin de
la versin 2 del programa desde la funcin main y con los mismos argumentos que en el caso de
la versin 1.
Si ejecutamos la orden n (dos veces) para ejecutar las sentencias de las lneas 10 y 11,
podemos ver que ahora s ejecutamos el cuerpo del bucle. En la primera iteracin se deber
imprimir la primera opcin. No obstante, lo que realmente se va a imprimir es el valor de la
expresin *++argv. Podemos decirle al depurador que nos informe del valor de la expresin
ejecutando la orden p con un operando que es la expresin a evaluar.
p ++argv
El resultado puede verse en la gura 10.11. Puede observarse que la orden p permite obtener
el valor de una expresin, y en particular, que si esa expresin es un puntero a una cadena de
caracteres, lo que se obtiene es la cadena completa.
Ahora podemos ver por qu la salida de nuestro programa es incorrecta. La primera iteracin
del bucle de captura de las opciones no enva a la salida estndar la primera opcin, sino la
segunda directamente. Ello se debe a que la expresin utilizada para imprimir (*++argv) es
incorrecta. Justo antes de ejecutar la sentencia 12, argv apunta al puntero que a su vez apunta
a la cadena que contiene la opcin, as que la expresin que debera imprimirse mediante printf
es *argv omitiendo el operador ++.
Debemos, por tanto, salir del depurador, corregir el programa fuente, regenerar el ejecutable
y ejecutar de nuevo para ver el comportamiento ahora. El cdigo fuente corregido puede verse
en el listado 10.2.
10.1. Una sesin de depuracin con gdb 81
Figura 10.10: Ejecucin del depurador con la versin 2 del programa
Figura 10.11: Impresin del valor de una expresin
82 10.1. Una sesin de depuracin con gdb
1
#include <s t di o . h>
3 #include <s t r i ng . h>
5 void Pri nt I nf orme ( const char cadena ) ;
7 i nt main( i nt argc , char argv [ ] )
{
9
pr i nt f ( "Las opciones son: " ) ;
11 while(argc > 0 && (++argv ) [ 0 ] == -)
pr i nt f ( " %s " , argv ) ;
13
pr i nt f ( "\n" ) ;
15
pr i nt f ( "Otros argumentos de la linea de ordenes\n" ) ;
17 while ( argv++){
Pri nt I nf orme ( argv ) ;
19 argv++;
}
21
return 0;
23 }
25 void Pri nt I nf orme ( const char cadena )
{
27 i nt l ongi t ud ;
29 l ongi t ud = s t r l e n ( cadena ) ;
pr i nt f ( " %s\tlongitud= %d\n" , cadena , l ongi t ud ) ;
31
return ;
33 }
Listado 10.2: Programa ejemplo. Versin 3
10.1. Una sesin de depuracin con gdb 83
Figura 10.12: Salida de la versin 3
La salida de la nueva versin puede verse en la gura 10.12. Observamos que no hay errores
de compilacin ni enlace y que ahora las opciones se obtienen correctamente, pero al listar
los argumentos suplementarios (los que van a continuacin de las opciones), el programa sigue
fallando. No se listan ms que algunos y al nal se obtiene una excepcin de memoria.
Volveremos por tanto a ejecutar la nueva versin del programa bajo control del depurador
con los mismos datos que en los casos anteriores. Nuestro punto de ruptura lo situaremos ahora
al comienzo del segundo bucle while (lnea 17 del archivo fuente), que es el que debe imprimir
el resto de los argumentos y funciona incorrectamente. Al ejecutar, obtendremos la situacin
mostrada en la gura 10.13.
Podemos observar que se ha producido la impresin correcta de la lnea del informe de salida
que contiene las opciones de la lnea de rdenes y la impresin del rtulo de cabecera del informe
de los otros argumentos. Despus el depurador ha detenido la ejecucin al comienzo del bucle
while que debe imprimir esos argumentos.
Podemos ver cul es el siguiente argumento a procesar imprimiendo el valor de *argv y
despus ejecutar la lnea 17, lo cual nos llevar a detenernos antes de ejecutar la primera iteracin
del bucle. La situacin sera la de la gura 10.14.
Ahora no nos interesa usar la orden n para que el depurador ejecute la sentencia 18. Ello
ejecutara directamente la llamada a la funcin PrintInforme y la ejecucin se detendra antes
de ejecutarse la sentencia 19. Lo que nos interesa es que la ejecucin contine paso a paso dentro
de la funcin PrintInforme. Esto puede conseguirse mediante la orden s.
s
84 10.1. Una sesin de depuracin con gdb
Figura 10.13: Ejecucin del depurador con la versin 3 del programa
Figura 10.14: Primera iteracin del bucle de impresin de argumentos
10.1. Una sesin de depuracin con gdb 85
Figura 10.15: Traza de una funcin mediante la orden s
Si ejecutamos esa orden, el resultado que obtendremos es el mostrado en la gura 10.15.
Podemos observar que el depurador nos informa del valor del argumento que se pasa a la funcin.
En nuestro caso, la cadena --tres. Pero esto no es lo que esperbamos. El argumento que
debera haberse pasado es la cadena una. Ahora est claro por qu obtenemos --tres en
la primera lnea del informe de argumentos en nuestra ejecucin (errnea) del programa (ver
gura 10.12).
Si ahora ejecutamos la orden n, podemos almacenar en longitud la longitud de la cadena,
y luego, mediante la orden p podemos ver el valor de esa longitud. Si ahora ejecutamos n
repetidamente, obtendremos la primera lnea del informe, luego se ejecutar la sentencia de nal
de la funcin PrintInforme y se volver a la funcin main en la lnea 19; despus se vuelve de
nuevo a la cabecera del bucle. Todo ello puede verse en la gura 10.16.
La funcin PrintInforme hace su trabajo correctamente. Como hemos visto, lo que sucede
es que se le pasa un argumento incorrecto. En la cabecera del bucle se comprueba si *argv no
es nulo para ejecutar el cuerpo del bucle, y adems se incrementa argv, con nimo de utilizar
el siguiente argumento de la lnea de rdenes en la iteracin siguiente. Pero esto ltimo es
incorrecto, porque ello afecta a la llamada a PrintInforme. Es necesario modicar la sentencia
17 para no incrementar argv. El cambio de argumento de la lnea de rdenes lo har la sentencia
19.
Por otra parte este error explica la excepcin de memoria que obtenemos al nal. Al incre-
mentar indebidamente argv (de hecho lo incrementamos dos veces una en la lnea 17 y otra en
la 19) nos pasamos del nal de la tabla de punteros sin detectar el puntero nulo que seala su
n.
Como siempre, abortaremos la ejecucin del depurador, corregiremos el error en el programa
fuente, reconstruiremos el ejecutable y realizaremos la ejecucin de prueba. El cdigo corregido
puede verse en el listado 10.3. La salida de ejecucin puede verse en la gura 10.17.
86 10.1. Una sesin de depuracin con gdb
Figura 10.16: Primera ejecucin de la funcin PrintInforme
Figura 10.17: Salida de la versin nal
10.1. Una sesin de depuracin con gdb 87
1
#include <s t di o . h>
3 #include <s t r i ng . h>
5 void Pr i nt I nf orme ( const char cadena ) ;
7 i nt main( i nt argc , char argv [ ] )
{
9
pr i nt f ( "Las opciones son: " ) ;
11 while(argc > 0 && (++argv ) [ 0 ] == -)
pr i nt f ( " %s " , argv ) ;
13
pr i nt f ( "\n" ) ;
15
pr i nt f ( "Otros argumentos de la linea de ordenes\n" ) ;
17 while ( argv ){
Pri nt I nf orme ( argv ) ;
19 argv++;
}
21
return 0;
23 }
25 void Pr i nt I nf orme ( const char cadena )
{
27 i nt l ongi t ud ;
29 l ongi t ud = s t r l e n ( cadena ) ;
pr i nt f ( " %s\tlongitud= %d\n" , cadena , l ongi t ud ) ;
31
return ;
33 }
Listado 10.3: Programa ejemplo. Versin nal
88 10.2. Sugerencias
Ahora la salida obtenida es correcta para los datos utilizados y no se produce la excepcin
de memoria que antes originaba la terminacin anormal de la ejecucin del programa.
10.1.4. Otras rdenes tiles del depurador gdb
Durante la ejecucin de un programa bajo control del depurador gdb pueden utilizarse otras
rdenes que pueden ser de utilidad en otras situaciones. Una de las ms comunes es la orden l.
Su formato es
l [ ][ <numerodel i ne a >]
La orden l cuando se usa sin argumentos opcionales, lista las lneas del archivo fuente en
torno a la sentencia que vaya a ejecutarse (tpicamente cuando se usa por primera vez un
intervalo de 10 lneas en total). Ello sirve para podernos situar en el cdigo fuente y saber qu
sentencias hay antes o despus de la actual. Si se ejecuta l repetidamente se listan las lneas en
torno a la ltima listada la vez anterior.
Si se especica <numero-de-linea> se listan las lneas en torno a la linea indicada, no la
que toca ejecutar. Si se especica el signo - se listan las lneas previas a la actual o a la que
se indique.
Para ms informacin sobre las rdenes del depurador gdb consltese la pgina de informa-
cin sobre el depurador
i nf o gdb
en la lnea de rdenes del shell normal. La pgina de manual normal de gdb contiene un infor-
macin limitada.
10.2. Sugerencias
La solucin discutida en la seccin 10.1.3 para el programa ejemplo en su versin nal daba
una salida correcta para la lnea de rdenes utilizada, pero sigue siendo una solucin incorrecta.
Vase por ejemplo su comportamiento cuando se utiliza una lnea de rdenes vaca.
Se recomienda al lector que utilice el depurador para ver qu es lo que sucede y corrija el
problema como ejercicio para utilizar las tcnicas anteriores.
Parte IV
La utilidad make de GNU
89
Captulo 11
Introduccin
En el mbito del desarrollo y el mantenimiento de software, la realizacin de tareas complejas
basadas en el uso de mltiples recursos que son generados separadamente, es un proceso que,
cuando se realiza manualmente, es tedioso por lo repetitivo y muy propenso a errores.
Tomemos como ejemplo la construccin de uno o varios ejecutables a partir de los archivos
fuente en un ciclo de edicin-compilacin-enlace. Las operaciones de edicin de los archivos
fuente se realizan de modo interactivo y producen los recursos de partida para las otras dos
fases del ciclo de construccin, que, a su vez, se desarrollan en modo batch.
Si la compilacin de los archivos fuente se intenta hacer desde la lnea de rdenes del shell,
obtendremos frecuentemente informes de error correspondientes a los posibles errores sintcticos
que haya en los archivos fuente, lo cual nos llevar a intentar corregirlos y a las correspondientes
recompilaciones. El problema no es grave mientras nuestro proyecto se compone de unos pocos
archivos fuente, pero est clara la dicultad de controlar el proceso manualmente en cuanto la
escala aumenta.
Aparte de ello, debe tenerse en cuenta que, por razones de economa, deberan recompilarse
slo aquellos archivos en los que se hubieran registrado errores, y no los dems, pero lo nico
que es verdaderamente simple es recompilar todo cada vez, lo que, cuando la escala aumenta,
es inaceptable.
El asunto se complica si tenemos en cuenta que los productos de las compilaciones se deben
usar como archivos de entrada para la fase de enlace, en la que tambin pueden producirse
errores, que para ser corregidos pueden necesitar modicar los archivos fuente y por tanto
causar que deba realizarse al menos una recompilacin parcial.
Por ltimo, si nuestros ejecutables no funcionan como se esperaba, habr que modicar los
fuentes, y de nuevo nos encontramos con el mismo problema.
Las consideraciones anteriores slo se han referido al ciclo de construccin bsico, pero debe-
mos tener en cuenta que, durante el desarrollo, se suelen intentar mejoras en las implementacio-
nes, lo que conduce a nuevas versiones de algunos de los archivos fuente, con las consecuencias
correspondientes sobre la generacin de los ejecutables respectivos, proceso en el cual, algunos
fuentes anteriores no necesitan recompilarse pero otros s, etc.
Resulta evidente que las mismas consideraciones pueden hacerse respecto a otras tareas co-
munes en el tratamiento de informacin, como la generacin y mantenimiento de documentacin,
91
92
de donde se deriva el inters que, en el mbito profesional, tiene el uso de herramientas que nos
permitan controlar y automatizar estos procesos.
La utilidad make se usa para resolver esta clase de problemas y las siguientes pginas estn
dedicadas a una breve introduccin al uso elemental de la versin GNU de dicha herramienta
en el desarrollo de aplicaciones en lenguaje C, aunque gran parte de lo que se tratar puede
aplicarse casi sin cambios a la solucin del problema anlogo en otros lenguajes de programacin
o en otros tipos de tareas, as como a otras versiones de la utilidad make presentes en diferentes
sistemas de desarrollo.
Captulo 12
La utilidad make de GNU
Como ya hemos visto en el captulo 11, la utilidad make, en cualquiera de sus versiones,
permite la generacin y el mantenimiento ordenado de los archivos objeto y los ejecutables que
se obtienen a partir de otros archivos fuente, reduciendo las operaciones de compilacin y enlace
al mnimo necesario.
Para realizar su tarea, make utiliza un archivo denominado genricamente makele en el que
el programador especica un conjunto de reglas que make debe aplicar al objeto de conseguir
sus objetivos. La forma de especicar dichas reglas y su contenido son el objeto del presente
captulo.
La utilidad make se ejecuta habitualmente desde la lnea de rdenes del shell y el formato de
la orden es
i nf o make
Para consultar esa documentacin en otros formatos vase [3].
12.1. Funcionamiento bsico de make
La utilidad make funciona basndose en las reglas especicadas en el archivo makele. En
esas reglas se expresa, para cada archivo que deba construirse, de qu otros archivos depende.
Por ejemplo, puede decirse de qu archivos objeto depende un ejecutable que deba construir-
se.
Adems, en esas reglas se expresan las rdenes del shell que deben ejecutarse cuando el
archivo que queremos construir no existe o es ms antiguo que alguno de los archivos de los que
depende (se dice en ese caso que el archivo que necesitamos construir no est al da).
12.2. Sintaxis de los archivos makele
Un archivo makele es un archivo de texto puro, que puede prepararse por tanto con cualquier
editor de texto que permita escribir texto sin formato.
Los archivos makele pueden contener bsicamente comentarios, declaraciones de variables,
reglas que especican las acciones a realizar por make (ver seccin 12.1) y directivas que indican
a make algunas formas especiales de interpretacin del contenido del archivo makele.
En el listado 12.1 puede verse un ejemplo simple del contenido de un archivo makele.
En l pueden verse lneas como la 1 que es un comentario. Cualquier texto que siga la carcter
# hasta el n de lnea se considera un comentario y es ignorado por make.
Las lneas 3 a 8 son deniciones de variables. Por convenio, los nombres de variables se
escriben en maysculas. Los valores de las variables son cadenas de caracteres que siguen al
separador =. Posteriormente a la denicin, puede usarse el valor de la variable en cualquier
expresin que lo requiera mediante la sintaxis $(<nombre_de_variable>). Por ejemplo, en la
lnea 18 se est usando de esa forma el valor de la variable CC de esa manera.
Las lneas 12 a 27 contienen reglas. El contenido esencial de un archivo makele son las
reglas que dirigen la actividad de make.
Cada regla se compone de una lnea de cabecera y de cero o ms acciones que consisten en
rdenes que podrn ser ejecutadas condicionalmente por el shell. Entre cada regla y la siguiente
debe haber al menos una lnea en blanco.
12.3. Sintaxis de las reglas de un archivo makele
El formato genrico de una regla es
12.3. Sintaxis de las reglas de un archivo makele 95
1 # Ejemplo de makef i l e
3 CFLAGS = c ggdb Wall ans i
LNKFLAGS = ggdb Wall ans i
5 CC = gcc
7 OBJS = uno . o dos . o t r e s . o
NOMEXEC = e j e c ut abl e
9
.PHONY : cl ean
11
a l l : $ (NOMEXEC)
13
cl ean :
15 rm f ~ cor e $ (OBJS) $ (NOMEXEC)
17 $ (NOMEXEC) : $ (OBJS)
$ (CC) $ (LNKFLAGS) o $ (NOMEXEC) $ (OBJS)
19
uno . o : uno . c uno . h dos . h
21 $ (CC) $ (CFLAGS) o uno . o uno . c
23 dos . o : dos . c
$ (CC) $ (CFLAGS) o dos . o dos . c
25
t r e s . o : t r e s . c dos . h
27 $ (CC) $ (CFLAGS) o t r e s . o t r e s . c
Listado 12.1: Ejemplo de makele
96 12.4. Ejemplo de ejecucin de la orden make
_
make
Los efectos sern los siguientes: Al no usarse la opcin -f se utilizar como makele nuestro
archivo denominado precisamente makefile.
Al no proponerse ningn objetivo en la orden make se disparar la primera regla, que es la
que aparece en la lnea 12 del listado 12.1, y que como puede apreciarse, es una regla sin acciones
asociadas.
Esa regla, una vez sustituidos los valores de las variables que guran en ella, tiene la forma
a l l : e j e c ut abl e
El algoritmo 1 causar que se dispare la regla de las lneas 17-18, puesto que el nico prerre-
quisito de la regla Regla(all) es ejecutable. Una vez sustituidos los valores de las variables
que guran en ella, Regla(ejecutable) tiene la forma
_
`
make cl ean
Si lo hacemos as se disparar la regla cuyo objetivo es clean, que, una vez sustituidos los
valores de las variables, tiene la forma
_
`
cl ean :
rm f ~ cor e uno . o dos . o t r e s . o e j e c ut abl e
12.5. Reglas implcitas 99
Esta regla no tiene prerrequisitos, y su accin se ejecutar por tanto incondicionalmente.
Es evidente que la accin consiste en borrar todos los archivos objeto, ms el ejecutable ms
cualquier volcado de memoria producido por ejecuciones errneas previas (core) y los archivos
que las versiones previas de los archivos de texto que hayan sido modicadas con el procesador
de texto (tpicamente su nombre es el del archivo original terminado con el carcter ).
Ahora resulta claro por qu una regla como sta no debe ser la primera de un archivo makele.
Ello hara que fuera la que se ejecutara cuando usamos make sin argumentos, y eso no es lo que
habitualmente deseamos.
Por otra parte, si no se toman precauciones, la regla Regla(clean) puede dar algunos pro-
blemas. En particular, si existiera un archivo con nombre clean, como no hay prerrequisitos, se
considerara que est al da, y la accin no se ejecutara. Por si se produce esa circunstancia, es
necesario decirle a make que el objetivo clean no es un nombre de archivo, y que la accin de la
regla debe ejecutarse tanto si existe un archivo con ese nombre como si no; de hecho, la accin
tampoco produce un archivo con ese nombre. La forma de hacerlo en la versin GNU de make
es usar la directiva .PHONY tal como se hace en la lnea 10 del listado 12.1.
12.5. Reglas implcitas
En las secciones anteriores hemos descrito la utilizacin de reglas en los archivos makele. Las
reglas que guran en los archivos makele reciben el nombre de reglas explcitas. No obstante, los
diferentes sistemas operativos incorporan utilidades make que disponen de un catlogo de reglas
que aplican implcitamente a falta de reglas explcitas que especiquen cmo debe realizar make
su tarea. Esas reglas implcitas estn asociadas a los nombres de los objetivos y los prerrequisitos
(en particular a las extensiones de los nombres), aplicndose as ciertas reglas para compilar
archivos escritos en determinados lenguajes, mientras que para otros lenguajes se usan otras.
Para una informacin completa sobre el catlogo de reglas implcitas para la versin GNU
de make vase la informacin de manual de la utilidad make en [3] o en la documentacin en
lnea.
Bibliografa
[1] A. Afzal. Introduccin a UNIX. Un enfoque prctico. Prentice Hall, 1997.
[2] Free Software Foundation. BASH reference manual.
http://www.faqs.org/docs/bashman/bashref_toc.html, 2001.
[3] Free Software Foundation. GNU Make Manual. http://www.gnu.org/software/make/manual,
2006.
[4] Indiana University. UNIX command reference card.
http://www.indiana.edu/uitspubs/b017/b017.pdf, 1998.
101