Primeros pasos con el archivo MAKE

Makefile básico

Considere 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, normalmente 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 makefiles 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 comando. Por ejemplo, aquí hay un posible ejemplo de Makefile para el ejemplo anterior de hello wold.

Archivo Make básico

Hagamos un Makefile básico y guárdelo 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, la M mayúscula 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 los archivos MAKE). Una vez que este Makefile se escribe cada vez que el usuario escribe make (en el mismo directorio que el Makefile), make verificará si source.c se ha modificado (comprueba la marca de tiempo), si se ha modificado más recientemente que la salida, se ejecutará. la regla de compilación en la línea siguiente.

Variables en Makefiles

Dependiendo del proyecto, es posible que desee introducir algunas variables en su archivo de creación. Aquí hay un ejemplo de Makefile con variables presentes.

CFLAGS = -g -Wall

output: source.c
    gcc $< $(CFLAGS) -o [email protected]

Ahora vamos a explorar lo que sucedió aquí. En la primera línea, declaramos una variable llamada CFLAGS que contiene varios indicadores comunes que puede desear pasar al compilador, tenga en cuenta que puede almacenar tantos indicadores como desee en esta variable. Luego tenemos la misma línea que antes de decirle 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 prácticamente la misma que antes, pero se ha acortado 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, en este caso source.c. $(CFLAGS) es nuestra variable que definimos antes, pero tenga en cuenta que tuvimos que poner la variable entre paréntesis con un $ delante como este $(someVariable). Esta es la sintaxis para decirle a Make que expanda la variable a lo que escribió antes. Finalmente tenemos el símbolo [email protected], 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 representa salida.

Limpio

Hacer limpio es otro concepto útil para aprender sobre hacer archivos. Modifiquemos el Makefile de arriba

CFLAGS = -g -Wall
TARGETS = output

output: source.c
    gcc $< $(CFLAGS) -o [email protected]

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 algo común en los archivos MAKE, ya que le permite eliminar rápidamente todos los archivos binarios que produjo simplemente escribiendo $> make clean. Al escribir make clean, le dice al programa make que ejecute la regla de limpieza y luego make ejecutará el comando rm para eliminar todos sus objetivos.

Espero que esta breve descripción del uso de make lo 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 programadores * Makefiles*. Para obtener más información sobre el uso de make, un excelente recurso es https://www.gnu.org/software/make/manual/.

Definición de reglas

Inicio rápido

Una regla describe cuándo y cómo se crean ciertos archivos (los 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 reciente que el objetivo.

Las reglas siguen la siguiente sintaxis: (Tenga en cuenta que los comandos que siguen a una regla están sangrados por una tabulación)

targets: prerequisites
        <commands>

donde objetivos y prerrequisitos son nombres de archivo o nombres especiales reservados y comandos (si están presentes) son ejecutados por un shell para construir/reconstruir objetivos que están desactualizados.

Para ejecutar una regla, uno puede simplemente ejecutar el comando make en la terminal desde el mismo directorio donde reside el Makefile. Ejecutar make sin especificar el objetivo, ejecutará la primera regla definida en el Makefile. Por convención, la primera regla en el Makefile a menudo se denomina todos o predeterminado, y normalmente 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 fecha 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 crear los objetivos. Sin embargo, cuando la regla no crea un archivo y el objetivo es una variable ficticia, la regla siempre se ejecutará.

Reglas de patrones

Las reglas de patrones se utilizan para especificar varios objetivos y crear nombres de requisitos previos a partir de nombres de objetivos. Son más generales y más poderosas en comparación con las reglas ordinarias, ya que cada objetivo puede tener sus propios requisitos previos. En las reglas de patrón, se crea una relación entre un objetivo y un requisito previo en función de los prefijos, incluidos los nombres de ruta y los sufijos, o ambos.

Imagine que queremos construir los objetivos foo.o y bar.o, compilando scripts en C, foo.c y bar.c, respectivamente. Esto podría hacerse usando las siguientes reglas ordinarias:

foo.o: foo.c
    cc -c $< -o [email protected]

bar.o: bar.c
    cc -c $< -o [email protected]

donde variable automática $< es el nombre del primer requisito previo y [email protected] el nombre del destino (Puede encontrar una lista completa de variables automáticas [aquí](https://www.gnu.org/ software/make/manual/html_node/Automatic-Variables.html#Automatic-Variables)).

Sin embargo, como los objetivos comparten el mismo sufijo, las dos reglas anteriores ahora se pueden sustituir por la siguiente regla de patrón:

%.o: %.c
    cc -c $< -o [email protected]

Reglas implícitas

Las reglas implícitas le dicen a make cómo usar los métodos habituales para construir ciertos tipos de archivos de destino, que se usan con mucha frecuencia. make usa el nombre del archivo de destino para determinar qué regla implícita invocar.

El ejemplo de regla de patrón que vimos en la sección anterior, en realidad no necesita declararse 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 prerrequisitos foo.o y bar.o se construirán usando la regla implícita para la compilación C, antes de construir foo.

foo : foo.o bar.o
    cc -o foo foo.o bar.o $(CFLAGS) $(LDFLAGS)

Puede encontrar un catálogo de reglas implícitas y las variables utilizadas por ellas [aquí] [posix-implicit].

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 archivo MAKE consta de una sola regla que le indica a make cómo crear un archivo cuyo nombre termine en .gz si hay 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 con espacios y los espacios no se usan igual que las pestañas en un archivo MAKE.