Construcción o creación (uso del comando make)
Cuando creamos pequeños programas como los que hemos hecho hasta ahora, no resulta muy difÃcil el proceso de compilación y enlace. Pero cuando se crean proyectos grandes, con varios archivos fuente (15, 30 o más) y librerías resultaría muy difícil o hasta imposible.
Linux viene con la utilería make de GNU. make lee de un archivo conocido como make toda la información que necesita para crear su programa. Ésta utilería es tan importante y popular que se ha especificado como estándar de POSIX.
make
make de GNU busca automáticamente un archivo make llamado GNUmakefile. Sino lo encuentra, busca makefile, y si tampoco lo encuentra busca Makefile, y si tampoco lo encuentra dice “que mierdas, no juegues conmigo que no me gusta perder tiempo” XD. Estos son los nombres predeterminados, pero puedes crear un archivo con el nombre que quieras y especificar al make que lo utilice. Los archivos make contienen información acerca de la compilación y enlace de su programa, con una sintaxis muy específica que make puede entender.
make tiene una gran variedad de reglas integradas. Por ejemplo, sabe que los archivos que terminan con .c son archivos fuente de C, y sabe cómo compilarlos para convertirlos en archivos objeto (.o). Puedes redefinir cualquiera de estas reglas si gustas. En el caso más simple, todo lo que necesitas especificar en tu archivo make es el nombre que va a tener su archivo ejecutable, así como los archivos .o que se necesitan para crearlo.
He aquí un archivo sencillo para make, que creará el programa de los dados:
juego:juego.o tirador.o
$(CC) -o $@ juego.o tirador.o
Ahora podrás crear el programa con tan solo un comando: make.
Hay ocasiones en las que hay que indicar como compilar cierto tipo de archivo, por ejemplo cuando se utilizan otro tipo de extensiones (.cpp, .cxx, .c++). El error que se generaría sería similar a este:
make: *** No hay ninguna regla para construir el objetivo ‘juego.o’, necesario para ‘juego’. Alto.
Vamos a ver un ejemplo de archivo makefile en donde se especifica explícitamente como construir dichos archivos objeto:
juegodados: juego.o tirador.o
$(CC) -o $@ juego.o tirador.o
juego.o: juego.c
$(CC) -c juego.c
tirador.o: tirador.c
$(CC) -c tirador.c
Ahora veamos un archivo makefile aún más completo:
#Makefile para crear programa para tirar dados
CFLAGS = -O
OBJS = juego.o tirador.o
all=dado
juego: $(OBJS)
$(CC) $(CFLAGS) -o $@ $(OBJS)
juego.o: juego.c
$(CC) -c juego.c
tirador.o: tirador.c
$(CC) -c tirador.c
clean:
-$(RM) dado *.o
Este archivo make define una regla llamada clean, que se utiliza para eliminar todos los archivos previamente compilados (incluso el ejecutable) y empezar con un directorio limpio. Fíjate también que se pueden declarar una especie de variables (como CFLAGS, OBJS, etc.), que se pueden utilizar al momento de indicar algún comando. Además fíjate que se pueden utilizar comentarios con el símbolo #.
Y un último ejemplo más complejo no nos vendría mal. Vamos a ver como sería nuestro archivo makefile, si deseáramos utilizar bibliotecas compartidas (librerías dinámicas):
#Makefile para crear programa para tirar dados
#usando bibliotecas compartidas
CFLAGS = -O
OBJS = juego.o
LIBS=libtirar.so
all=dado
juego: $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) -L. -ltirar
juego.o: juego.c
$(CC) -c juego.c
tirador.o: tirador.c
$(CC) -fPIC -c $<
libtirar.so: tirador.o
-$(RM) libtirar*
$(CC) -shared -Wl,-soname,libtirar.so.1 \
-o libtirar.so.1.0 $<
ln -slibtirar.so.1.0 libtirar.so.1
ln -slibtirar.so.1 libtirar.so
clean:
-$(RM) dado *.o libtirar*
Importante!!!
Sino quieres tener problemas en el futuro lee esto: la sintaxis de make nos obliga a respetar los separadores. ¿qué son separadores? talvez te hayas fijado en la forma en que están tabulados los archivos. Esto no es maña mÃa ni mucho menos, esto es una regla para los archivos make; sino se tabularan lo más seguro es que en la ejecución del make apareciera este error:
makefile:2: *** falta un separador. Alto.
Así que por lo que más quieras: utiliza los separadores si quieres que funcione.
Opciones de línea de comandos de make
make tiene varias opciones útiles de línea de comandos. Por ej., si quieres especificar un archivo make alternativo, en lugar de los predeterminados, invoca a make de la siguiente forma:
make -f nombrearchivo
make es un programa muy sofisticado. Una de las cosas que hace es comprender las dependencias. Por ejemplo, sabe que los archivos .o se crean a partir de archivos .c. Tu programa puede consistir en varios archivos fuente .c. Si cambias uno, no es necesario volver a compilarlos todos cada vez que vayas a crearlo. Sólo necesitas volver a compilar el archivo fuente que haya cambiado. make comprende esto y compila solo aquellos archivos que no estén actualizados. Algunas veces será necesario que veas primero qué es lo que make necesita para crear el programa. Puedes hacer esto con el siguiente comando:
make -n
Esto le indica a make que analice el makefile y que reporte qué comandos emitirá para crear el programa. make no ejecutará ningún comando.
5 Comentarios | deja el tuyo





Hola,
primero querría agradecerte tu post, me parece muy interesante.
Luego quería preguntarte a cerca de un problema que tengo al intentar compilar un proyecto en Eclipse sobre Ubuntu 9.04.
Cuando lanzo un Build Project sobre este Makefile:
#Makefile created by Jorge Fandos
objects = BatchTokenizer.o tokenizer.o
sources = BatchTokenizer.cpp tokenizer.cpp
target = BatchTokenizer
headers = tokenizer.h
$(target): $(objects)
$(CC) -o $(target) $(objects)
$(objects): $(sources) $(headers)
$(CC) -c $(sources)
all: $(target)
clean:
rm -f $(object) $(target)
Me llevo este error:
***falta un separador. Alto linea 7.
No acabo de ver por qué.
Tendrías tú alguna idea sobre el problema.
Gracias por tu ayuda.
Hola…
me han dejado la tarea de investigar cómo funciona make, ha sido clara tu explicación, sólo que aún me quedan dudas con los compiladores y como correrlo, yo uso dev c para programar en C, también no entendí bine que quiere decir “$(cc)”
Saludos!
gracias x el post.
Al hacer $(**) capturas el valor del argumento (dicho mal y pronto). O sea si CC=gcc, cuando hagas $(CC) lo va a reemplazar por gcc. Por otro lado se usa CC para denominar al compilador. Por eso a Jorge no le funcionaba y justamente le estaba avisando, algo no esta definido y para colmo el propio compilador
Saludos.
Qué tal! Cómo puedo definir parámetros que recibirá al ejecutar el programa?
Por ejemplo: si quiero escribir
$ miprograma -o archivo.mio
para indicar con “-o” que el resultado de la ejecución debe ser escrito en “archivo.mio”
Cómo debo ejecutar make y cómo debe recibirlo mi programa (en mi caso, un .jar)?
hola disculpa por mi ignorancia pero estoy tratando de instalar un plugin de compiz pero como no existe el makefile esto es lo que pasa al tratar de compilarlo
christian@anonimus:~/compiz/plugins-extra$ make
make: *** No se especificó ningún objetivo y no se encontró ningún makefile. Alto.
y pues ya no se que mas hacer por que no encuentro ayuda por toda la web o bueno por todas las paginas que e buscado. esta es una captura de la carpeta donde esta el plugin http://fotos.subefotos.com/94421b8088d208671ba75923dd72da15o.png
el sistema operativo que estoy usando es ubuntu 10.04, espero me puedas ayudar gracias