Compilando en el Shell (Unix)
El compilador de C
normalmente corre bajo el nombre de cc o gcc. Para obtener
información completa de las opciones de compilación ver
man gcc (cc normalmente es
un link a gcc). Para compilar C++ usar el compilador g++.
Algunas opciones:
Alternativamente:
cc -o longestLine longestLine.c getline.c copy.c
Makefiles
Descripción
El comando Make nos permite administrar grupos de programas. En la medida que trabajamos con programas más largos, el proceso de recompilación toma más tiempo. Por otro lado notamos que generalmente estamos trabajando en una sección reducida del programa y el resto permanece sin cambio. El programa make nos ayuda a desarrollar grandes programas al mantener registro de las partes del programa que han cambiado, así compila sólo aquella parte modificada desde la última compilación.
Compilación simple
El comando en este caso es simple: cc file.c , pero hay tres pasos antes de llegar al ejecutable final.
Compilación de varios archivos
Cuando el programa es más grande o tiene varias unidades lógicas, tiene sentido dividir el código fuente en archivos separados .c más fáciles de manejar. En este caso el comando será: cc green.c blue.c
Compilación Separada
El proceso puede ser dividido en dos compilaciones y un ligado.
La opción -c permite avanzar sólo el paso en rojo. cc -c green.c generará así green.o pero no a.out.
para producir el ejecutable en este caso se deberá hacer:
cc -c green.c
cc -c blue.c
cc green.o blue.o
Grafo de Dependencias
make opera en base a las dependencias de los archivos. Por ejemplo para crear program.o se requiere program.c Puede haber otras dependencias con program.h también.
Ahora, si hacemos un cambio en un archivo make puede darse cuenta qué archivos deben ser recompilados para generar una nueva versión del proyecto.
¿Cómo trabaja make?
El comando make obtiene el grafo de dependencia de un archivo de texto llamado makefile o Makefile.
Construcción del archivo Makefile
El formato básico es:
target : archivos_fuente(s)Podemos poner comentarios poniendo el signo # como primer caracter de la línea.
comando(s) (debe ser precedido por un tab)
Usando Makefile con make
Una vez construido basta con invocar:
%make
make lee el archivo makefile o Makefile del directorio actual y lo procesa. En este caso el resultado sería:
% make
cc -c data.c
cc -c main.c
cc -c io.c
cc data.o main.o io.o -o project1
%
Uso de Macros
Se pueden definir macros para almacenar nombres. El formato es:
OBJECTS = data.o io.o main.o
Cuando queremos usar la macro (queremos usar su valor) lo hacemos con el string $(OBJECTS).Por ejemplo:
OBJECTS = data.o main.o io.oTambién se pueden especificar los valores de una macro en la línea de comando de make.
project1: $(OBJECTS)
cc $(OBJECTS) -o project1
data.o: data.c data.h
cc -c data.c
main.o: data.h io.h main.c
cc -c main.c
io.o: io.h io.c
cc -c io.c
make 'OBJECTS=data.o newio.o main.o' project1
Esto escribe sobre el valor de OBJECTS definido dentro de Makefile
Macros especiales
Hay algunas macros ya definidas y usadas por make. Algunas son:
CC
Se refiere al compilador C actual. Por defecto cc.
$@
Nombre completo del "target" actual
$?
La lista de dependencias actuales fuera de fecha.
$<
El archivo fuente de la dependencia actual.
Se puede manipular algunas macros. por ejemplo: si OBJS = data.o io.o main.o, y usamos $(OBJS:.o=.c) en el Makefile sustituirá .o al final por .c, Este conducirá a : data.c io.c main.c
Reglas predefinidas
Make sabe que para generar un archivo .o requiere del correspondiente .c y hace cc -c program.c
Por lo anterior no es necesario especificar todo y podemos reducir nuestro archivo makefile.
OBJECTS = data.o main.o io.oMás simplificaciones:
project1: $(OBJECTS)
cc $(OBJECTS) -o project1
data.o: data.h
main.o: data.h io.h
io.o: io.h
Es posible poner más de un archivo en la sección target de la regla de dependencia. En este caso la dependencia es el and entre todas.
OBJECTS = data.o main.o io.oSignifica que main.o depende de data.h y io.h además de main.c que no es necesario anotar,.
project1: $(OBJECTS)
cc $(OBJECTS) -o project1
data.o main.o: data.h
io.o main.o: io.h
Uso de sufijos
Make tiene un target especial llamada .SUFFIXES que permite definir sufijos. Por ejemplo la línea de dependencia:
.SUFFIXES: .cpp
Le indica a make que usaré estos sufijos especiales para construir mis reglas:
Ahora así como make sabe construir .o a partir de .c, yo puedo indicar:
.cpp.o:
$(CC) -c $<
o más corto aún
.cpp.o: ; $(CC) -c $<
Más información: ver man make y el manual GNU de make
Para el ejemplo anterior
el archivo makefile es:
longestLine: longestLine.o getline.o copy.o
cc -o longestLine longestLine.o getline.o copy.o
longestLine.o: longestLine.c longestLine.h
cc -c longestLine.c
getline.o: getline.c longestLine.h
cc -c getline.c
copy.o: copy.c
cc -c copy.c
Una forma más completa para un archivo makefile es:
# Definiciones Macro para una aplicación "estándar".
#
# Definición de flags de compilación
FLAGS=-g -DDEBUG
#
# comandos para la compilación
.SUFFIXES: .cpp .c .h .o
.c.o: ; cc $(FLAGS) -c $*.c
.cc.o: ; gcc $(FLAGS) -c $*.cc
.cpp.o: ; gcc $(FLAGS) -c $*.cpp
#
# Tareas
longestLine: longestLine.o getline.o copy.o
cc $(FLAGS) -o
longestLine longestLine.o getline.o copy.o
longestLine.o: longestLine.c longestLine.h
getline.o: getline.c longestLine.h
copy.o: copy.c
clean:
rm *.o