makefile Tutorial
Empezando con makefile
Buscar..
Observaciones
Un makefile es un archivo de texto que controla el funcionamiento del programa make
. El programa make
se usa normalmente para administrar la creación de programas a partir de sus archivos de origen, pero se puede usar más generalmente para manejar cualquier proceso en el que los archivos (o destinos ) deban regenerarse después de que otros archivos (o requisitos previos ) hayan sido modificados. El archivo make describe la relación entre los objetivos y los requisitos previos, y también especifica los comandos necesarios para actualizar el objetivo cuando uno o más de los requisitos previos han cambiado. La única forma en que make
determina "fuera de fecha" es comparando la hora de modificación de los archivos de destino y sus requisitos previos.
Los makefiles son algo únicos en algunos aspectos, lo que puede ser confuso inicialmente.
Primero, un makefile consiste en dos lenguajes de programación completamente diferentes en el mismo archivo. La mayor parte del archivo está escrito en un lenguaje que make
que se pueda entender: esto proporciona asignación y expansión de variables, algunas capacidades de preprocesador (incluidos otros archivos, análisis condicional de secciones del archivo, etc.), así como la definición de objetivos y su prerrequisitos Además, cada objetivo puede tener una receta asociada que especifica qué comandos deben invocarse para hacer que ese objetivo se actualice. La receta está escrita como un script de shell (POSIX sh por defecto). El programa make
no analiza este script: ejecuta un shell y pasa el script al shell que se ejecutará. El hecho de que las recetas no sean analizadas por make
, sino que son manejadas por un proceso de shell separado, es fundamental para entender los makefiles.
En segundo lugar, un makefile no es un lenguaje de procedimiento como un script: como make
analiza el makefile, construye un gráfico dirigido internamente donde los objetivos son los nodos del gráfico y las relaciones de requisitos previos son los bordes. Sólo después de que todos los archivos make han sido completamente analizada y la gráfica es completa se make
elegir un nodo (objetivo) y tratar de llevarlo hasta la fecha. Para garantizar que un objetivo esté actualizado, primero debe asegurarse de que cada uno de los requisitos previos de ese objetivo esté actualizado, y así sucesivamente.
Versiones
Nombre | También conocido como | Versión inicial | Versión | Fecha de lanzamiento |
---|---|---|---|---|
Hacer POSIX | 1992 | IEEE Std 1003.1-2008, Edición 2016 | 2016-09-30 | |
Hacer NetBSD | bmake | 1988 | 20160926 | 2016-09-26 |
GNU hace | gmake | 1988 | 4.2.1 | 2016-06-10 |
Marca SunPro | dmake | 2006 | 2015-07-13 | |
MSVS nmake | 2003 | 2015p3 | 2016-06-27 |
Makefile básico
Considera escribir un "¡Hola mundo!" programa en c. Digamos que nuestro código fuente está en un archivo llamado source.c, ahora para ejecutar nuestro programa necesitamos compilarlo, generalmente en Linux (usando gcc) necesitaríamos escribir $> gcc source.c -o output
donde salida Es el nombre del ejecutable que se generará. Para un programa básico, esto funciona bien, pero a medida que los programas se vuelven más complejos, nuestro comando de compilación también puede volverse más complejo. Aquí es donde entra un Makefile , los makefile nos permiten escribir un conjunto bastante complejo de reglas sobre cómo compilar un programa y luego simplemente compilarlo escribiendo make en la línea de comandos. Por ejemplo, aquí hay un posible ejemplo de Makefile para el ejemplo anterior de hello wold.
Makefile básico
Permite crear un Makefile básico y guardarlo en nuestro sistema en el mismo directorio que nuestro código fuente llamado Makefile . Tenga en cuenta que este archivo debe llamarse Makefile, sin embargo, el capitolio M es opcional. Dicho esto, es relativamente estándar usar un capitolio M.
output: source.c
gcc source.c -o output
Tenga en cuenta que hay exactamente una pestaña antes del comando gcc en la segunda línea (esto es importante en makefiles). Una vez que este Makefile se escribe cada vez que los tipos de usuario make (en el mismo directorio que Makefile) make verificará si se ha modificado source.c (verifica la marca de tiempo) si se ha modificado más recientemente que la salida, se ejecutará La regla de compilación en la siguiente línea.
Variables en Makefiles
Dependiendo del proyecto, es posible que desee introducir algunas variables en su archivo make. Aquí hay un ejemplo de Makefile con variables presentes.
CFLAGS = -g -Wall
output: source.c
gcc $< $(CFLAGS) -o $@
Ahora vamos a explorar lo que pasó aquí. En la primera línea, declaramos una variable llamada CFLAGS que contiene varias banderas comunes que tal vez desee pasar al compilador, tenga en cuenta que puede almacenar tantas banderas como desee en esta variable. Luego tenemos la misma línea que antes de indicar a make que verifique source.c para ver si se ha cambiado más recientemente que la salida, si es así, ejecuta la regla de compilación. Nuestra regla de compilación es casi la misma que antes, pero se acortó mediante el uso de variables, la variable $<
está integrada en make (conocida como una variable automática, consulte https://www.gnu.org/software/make/manual/ html_node / Automatic-Variables.html ) y siempre representa la fuente, por lo que en este caso source.c . $(CFLAGS)
es nuestra variable que definimos anteriormente, pero tenga en cuenta que tuvimos que poner la variable entre paréntesis con $ delante como esta $(someVariable)
. Esta es la sintaxis para decirle a Make que expanda la variable a lo que escribiste antes. Finalmente, tenemos el símbolo $ @, una vez más, esta es una variable integrada en make, y simplemente representa el objetivo del paso de compilación, por lo que en este caso significa salida .
Limpiar
Hacer limpio es otro concepto útil para aprender sobre crear archivos. Permite modificar el Makefile desde arriba
CFLAGS = -g -Wall
TARGETS = output
output: source.c
gcc $< $(CFLAGS) -o $@
clean:
rm $(TARGETS)
Como puede ver, simplemente agregamos una regla más a nuestro Makefile y una variable adicional que contiene todos nuestros objetivos. Esta es una regla un tanto común a tener en makefiles, ya que le permite eliminar rápidamente todos los archivos binarios que produjo simplemente escribiendo $> make clean
. Al teclear make clean le dices al programa make que ejecute la regla de limpieza y luego make ejecutará el comando rm para eliminar todos tus objetivos.
Espero que esta breve descripción del uso de make le ayude a acelerar su flujo de trabajo. Makefiles puede volverse muy complejo, pero con estas ideas debería poder comenzar a usar make y tener una mejor comprensión de lo que está sucediendo en otros Makefiles de programadores. Para obtener más información sobre el uso de Make a excellent resource, visite https://www.gnu.org/software/make/manual/ .
Definiendo reglas
Inicio rápido
Una regla describe cuándo y cómo se crean ciertos archivos ( objetivos de la regla). También puede servir para actualizar un archivo de destino si alguno de los archivos necesarios para su creación ( requisitos previos del objetivo) es más nuevo que el de destino.
Las reglas siguen la sintaxis a continuación: (Tenga en cuenta que los comandos que siguen una regla están sangrados por una pestaña )
targets: prerequisites
<commands>
donde los destinos y prerrequisitos son nombres de archivos o nombres reservados especiales y los comandos (si están presentes) son ejecutados por un shell para crear / reconstruir los objetivos que están desactualizados.
Para ejecutar una regla, simplemente puede ejecutar el comando make
en el terminal desde el mismo directorio donde reside el archivo Makefile . Ejecutar make
sin especificar el destino, ejecutará la primera regla definida en el Makefile . Por convención, la primera regla en el Makefile a menudo se llama todo o por defecto , comúnmente enumera todos los objetivos de compilación válidos como requisitos previos.
make
solo ejecuta la regla si el objetivo está desactualizado, lo que significa que no existe o que su tiempo de modificación es anterior a cualquiera de sus requisitos previos. Si la lista de requisitos previos está vacía, la regla solo se ejecutará cuando se invoque por primera vez para construir los objetivos. Sin embargo, cuando la regla no crea un archivo y el destino es una variable ficticia, la regla siempre se ejecutará.
Reglas de patrón
Las reglas de patrón se utilizan para especificar múltiples destinos y construir nombres de requisitos previos a partir de nombres de destino. Son más generales y más potentes en comparación con las reglas comunes, ya que cada objetivo puede tener sus propios requisitos previos. En las reglas de patrón, una relación entre un objetivo y un requisito previo se construye en base a los prefijos que incluyen nombres de ruta y sufijos, o ambos.
Imagina que queremos construir los objetivos foo.o
y bar.o
, compilando los scripts C, foo.c
y bar.c
, respectivamente. Esto podría hacerse usando las reglas ordinarias a continuación:
foo.o: foo.c
cc -c $< -o $@
bar.o: bar.c
cc -c $< -o $@
donde variable automática $<
es el nombre del primer requisito previo y $@
el nombre del objetivo ( aquí se puede encontrar una lista completa de variables automáticas).
Sin embargo, como los objetivos comparten el mismo sufijo, las dos reglas anteriores ahora pueden sustituirse por la siguiente regla de patrón:
%.o: %.c
cc -c $< -o $@
Reglas implícitas
Las reglas implícitas dicen make
cómo utilizar métodos habituales para construir ciertos tipos de archivos de destino, que se utilizan muy a menudo. make
utiliza el nombre del archivo de destino para determinar qué regla implícita se debe invocar.
El ejemplo de regla de patrón que vimos en la sección anterior, en realidad no necesita ser declarado en un Makefile ya que make
tiene una regla implícita para la compilación de C. Por lo tanto, en la siguiente regla, los requisitos previos foo.o
y bar.o
se compilarán utilizando la regla implícita para la compilación de C, antes de construir foo
.
foo : foo.o bar.o
cc -o foo foo.o bar.o $(CFLAGS) $(LDFLAGS)
Un catálogo de reglas implícitas y las variables utilizadas por ellas se pueden encontrar aquí .
regla genérica para gzip un archivo
Si un directorio contiene 2 archivos:
$ ls
makefile
example.txt
y makefile
contienen el siguiente texto
%.gz: %
gzip $<
entonces puede obtener example.txt.gz
escribiendo en el shell
$ make -f makefile example.txt.gz
el makefile consisten de una sola regla que instruya a hacer cómo crear un archivo cuyo nombre final con .gz si existe un archivo con el mismo nombre pero con el sufijo .gz.
makefile hola mundo
C: \ makefile:
helloWorld :
[TAB]echo hello world
ejecutar resultados:
C:\>make
echo hello world
hello world
Nota: [TAB] debe reemplazarse por una pestaña real, stackoverflow reemplaza las pestañas por espacios, y los espacios no se usan igual que las pestañas en un archivo make.