Articles

¿Qué es un Makefile y cómo funciona?

Posted by admin

si desea ejecutar o actualizar una tarea cuando se actualizan ciertos archivos, la utilidad make puede ser útil. El make utilidad requiere un archivo, Makefile (o makefile), que define el conjunto de tareas a ser ejecutadas. Puede haber utilizado make para compilar un programa a partir del código fuente. La mayoría de los proyectos de código abierto usan make para compilar un binario ejecutable final, que luego se puede instalar usando make install.,

en este artículo, exploraremos make y Makefile usando ejemplos básicos y avanzados. Antes de comenzar, asegúrese de que make esté instalado en su sistema.

ejemplos básicos

comencemos imprimiendo el clásico «Hello World» en la terminal. Crear un directorio vacío myproject que contiene un archivo Makefile con este contenido:

say_hello:
echo "Hello World"

Ahora, ejecute el archivo escribiendo make dentro del directorio myproject., La salida será:

$ make
echo "Hello World"
Hello World

En el ejemplo anterior, say_hello se comporta como un nombre de función, como en cualquier lenguaje de programación. Esto se llama el objetivo. Los prerrequisitos o dependencias siguen al destino. En aras de la simplicidad, no hemos definido ningún prerrequisito en este ejemplo. El comando echo "Hello World" se llama la receta. La receta utiliza requisitos previos para hacer un objetivo. El objetivo, los requisitos previos y las recetas juntos forman una regla.,

para resumir, a continuación se muestra la sintaxis de una regla típica:

target: prerequisites
<TAB> recipe

como ejemplo, un destino puede ser un archivo binario que depende de los requisitos previos (archivos de origen). Por otro lado, un prerrequisito también puede ser un destino que depende de otras dependencias:

no es necesario que el destino sea un archivo; podría ser solo un nombre para la receta, como en nuestro ejemplo. A estos los llamamos «objetivos falsos».,»

volviendo al ejemplo anterior, cuando se ejecutó make, se mostró todo el comando echo "Hello World", seguido de la salida real del comando. A menudo no queremos eso. Para suprimir el eco de la orden real, tenemos que empezar a echo @:

say_hello:
@echo "Hello World"

Ahora, intente ejecutar make nuevo., La salida debe mostrar sólo esto:

$ make
Hello World

Vamos a agregar un par más falso objetivos: generate y clean para el Makefile:

Si tratamos de ejecutar make después de los cambios, sólo el destino say_hello será ejecutado. Esto se debe a que solo el primer destino en el makefile es el destino predeterminado. A menudo llamado el objetivo predeterminado, esta es la razón por la que verá all como el primer objetivo en la mayoría de los proyectos., Es responsabilidad de all llamar a otros destinos. Podemos anular este comportamiento usando un objetivo falso especial llamado .DEFAULT_GOAL.

vamos a incluir que al principio de nuestro makefile:

.DEFAULT_GOAL := generate

esto ejecutará el objetivo generate como el valor predeterminado:

$ make
Creating empty text files...
touch file-{1..10}.txt

como su nombre indica, el objetivo falso .DEFAULT_GOAL solo puede ejecutar un objetivo a la vez. Esta es la razón por la que la mayoría de los makefiles incluyen all como un destino que puede llamar a tantos destinos como sea necesario.,

vamos a incluir el objetivo falso all y eliminar .DEFAULT_GOAL:

antes de ejecutar make, vamos a incluir otro objetivo falso especial, .PHONY, donde definimos todos los destinos que no son Archivos. make ejecutará su receta independientemente de si existe un archivo con ese nombre o cuál es su última hora de modificación., Aquí está la completa makefile:

El make debe llamar say_hello y generate:

$ make
Hello World
Creating empty text files...
touch file-{1..10}.txt

es una buena práctica para no llamar clean en el all o ponerlo como el primer objetivo., clean se debe llamar manualmente cuando se necesita limpieza como primer argumento para make:

$ make clean
Cleaning up...
rm *.txt

ahora que tiene una idea de cómo funciona un makefile básico y cómo escribir un makefile simple, veamos algunos ejemplos más avanzados.

ejemplos avanzados

Variables

en el ejemplo anterior, la mayoría de los valores de destino y prerrequisitos están codificados, pero en proyectos reales, estos se reemplazan con variables y patrones.,

la forma más sencilla de definir una variable en un makefile es usar el operador =., Por ejemplo, para asignar el comando gcc variable CC:

CC = gcc

Este es también llamada recursiva ampliado de la variable, y se utiliza en una regla, como se muestra a continuación:

hello: hello.c
${CC} hello.c -o hello

Como usted puede haber adivinado, la receta se expande como a continuación cuando se pasa a la terminal:

gcc hello.c -o hello

Ambos ${CC} y $(CC) son referencias válidas para llamar a gcc. Pero si uno intenta reasignar una variable a sí mismo, causará un bucle infinito., Vamos a verificar esto:

CC = gcc
CC = ${CC}
all:
@echo ${CC}

Ejecutar make dará como resultado:

$ make
Makefile:8: *** Recursive variable 'CC' references itself (eventually). Stop.

para evitar este escenario, podemos usar el operador := esto también se llama la variable simplemente expandida). No deberíamos tener ningún problema ejecutando el makefile de abajo:

CC := gcc
CC := ${CC}
all:
@echo ${CC}

patrones y funciones

el makefile siguiente puede compilar todos los programas de C usando variables, patrones y funciones., Vamos a explorarlo línea por línea:

a continuación se muestra la reescritura del makefile anterior, suponiendo que se coloca en el directorio que tiene un solo archivo foo.c:

Leave A Comment