Red de conocimiento informático - Aprendizaje de programación - ¿Cuál es el significado del comando make makefiles en Linux?

¿Cuál es el significado del comando make makefiles en Linux?

Ya sea en un entorno Linux o Unix, make es un comando de compilación muy importante. Ya sea que esté desarrollando su propio proyecto o instalando una aplicación, a menudo necesitará utilizar

make o make

install. La herramienta make le permite dividir grandes proyectos de desarrollo en módulos más manejables, y para una aplicación con cientos de archivos fuente, puede usar make y la herramienta makefile para limpiar interrelaciones complejas entre archivos fuente. Ante tantos archivos fuente, sería un desastre si el programador tuviera que escribir el comando gcc cada vez para compilarlos. La herramienta make, por otro lado, automatiza el proceso de compilación y compila solo las partes que el programador ha modificado desde la última compilación. Por lo tanto, el uso eficaz de las herramientas make y makefile puede mejorar en gran medida la eficiencia del desarrollo de proyectos. Además, una vez que domines make y makefiles, nunca te perderás al desarrollar aplicaciones de Linux.

Desafortunadamente, muchos libros sobre aplicaciones de Linux no cubren en detalle esta poderosa pero compleja herramienta de compilación. Aquí te presentaré make y su documentación

makefile.

Archivo Makefile

La función más importante y básica de la herramienta make es describir la relación entre los programas fuente y mantener automáticamente la compilación a través del archivo makefile. Los archivos Makefile son una forma común para que muchos compiladores (incluidos los de Windows NT) mantengan la información de compilación. Los archivos Makefile son una forma común para que muchos compiladores (incluidos los de Windows NT) mantengan la información de compilación, pero los usuarios deben modificar el archivo Makefile a través de una interfaz fácil de usar en el entorno de desarrollo integrado.

En sistemas UNIX, es habitual utilizar Makefile como archivo makfile. Si desea utilizar otro archivo como archivo MAKE, puede especificar el archivo MAKE usando la opción de comando make, de la siguiente manera:

$ make -f Makefile.debug

Por ejemplo, un makefile llamado prog El programa se compone de tres archivos fuente C (filea.c, fileb.c y filec.c) y el archivo de biblioteca LS. Normalmente, el compilador de C generará tres archivos objeto: filea.o, fileb.o y. filec.o. Supongamos que filea.c y fileb.c declaran un archivo llamado defs, pero filec.c no.

En otras palabras, existe una declaración de este tipo en filea.c y fileb.c:

#include "defs"

Luego, el siguiente archivo describe la relación entre estos archivos Interconectados:

#Este es un ejemplo que describe un programa makefile

: filea.o fileb.o filec.o

cc filea.o fileb.o filec.o - LS -o prog

filea.o: filea.c a.h defs

cc -c filea.c

fileb.o: fileb c b .h defs.

cc -c fileb.c

filec.o : filec.c c.h

cc -c filec.c

Esta descripción El archivo es un archivo MAKE simple.

Observe en el ejemplo anterior que la primera línea con el carácter # es una línea de comentario. La primera línea que no es de comentario especifica que prog se genera vinculando tres archivos objeto, filea.o, fileb.o y filec.o. Las siguientes líneas 4, 6 y 8 especifican tres archivos de destino respectivamente, así como los archivos .c, .h y defs de los que dependen. Las líneas 5, 7 y 9 especifican cómo construir el archivo de destino a partir de los archivos de los que depende.

Si el archivo filea.c o a.h se modifica después de la compilación, la utilidad make recompilará automáticamente filea.o, pero si filea.C o a.h no se modifica entre compilaciones y la prueba o aún existe, no es necesario volver a compilar. Esta dependencia es especialmente importante al compilar un programa que contiene varios archivos fuente. Al definir estas dependencias, la herramienta make puede evitar una gran cantidad de trabajo de compilación innecesario. Por supuesto, la compilación automática es posible usando un script Shell

, pero un script Shell compilará cualquier archivo fuente, incluidos aquellos que no necesitan ser recompilados, mientras que la utilidad make lo compilará según el tiempo. y la fecha en que se compiló por última vez el destino. El destino depende del estado de actualización del archivo fuente y determina automáticamente el archivo fuente que se compilará.

Como archivo descriptivo, el Makefile normalmente necesita contener:

◆ Definiciones de macros

◆ Interdependencias entre archivos fuente

◆ Ejecutable Comando

Makefile permite el uso de macros simples para hacer referencia a archivos fuente y su información de compilación relacionada. Una macro se puede citar simplemente anteponiendo la variable con el signo $, pero vale la pena señalar que si el nombre de la variable excede un carácter, se debe citar entre paréntesis (). Las siguientes son todas referencias de macro válidas:

$(CFLAGS)

$2

$Z

$(Z)

Las dos últimas referencias son idénticas. Una cosa a tener en cuenta son las variables predefinidas de algunas macros en los sistemas Unix, $*, $@, $? y $lt son cuatro macros especiales cuyos valores cambiarán en consecuencia durante la ejecución del comando, mientras que en GNU hay más variables predefinidas; definido en make. Para obtener más información sobre variables predefinidas, el uso de macros es una excelente manera de deshacerse de las tediosas opciones de compilación y facilitar la escritura de archivos MAKE

.

# Definir una macro para archivos objeto

OBJECTS= filea.o fileb.o filec.o

# Definir una macro para archivos de biblioteca

LIBES= -LS

# Definir una macro para el archivo de biblioteca

LIBES= -LS

.

# Usar macros Reescribir makefile

prog: $(OBJECTS)

cc $(OBJECTS) $(LIBES) -o prog

......

En este momento, si ejecuta el comando make sin parámetros, los tres archivos objeto y el archivo de biblioteca LS se vincularán; sin embargo, si agrega una nueva definición de macro después del comando make:

<; p> make "LIBES= -LL -LS"

La definición de macro que sigue a la línea de comando sobrescribirá la definición de macro en el archivo MAKE. Si LL también es un archivo de biblioteca, el comando make vincula los tres archivos de objetos y los dos archivos de biblioteca, LS y LL.

En sistemas Unix, la constante NULL no está claramente definida, por lo que cuando queramos definir una cadena NULL, debemos utilizar la siguiente definición de macro:

STRINGNAME=

comando make

El comando make puede ir seguido no solo de definiciones de macro, sino también de otros parámetros de línea de comando que especifican el archivo de destino que se compilará. El formato estándar es:

destino1 [destino2...]:[:][dependiente1...][;comandos][#...]

[(tab) comandos ][# ...]

Los corchetes son opcionales; los archivos de destino y los archivos dependientes pueden contener caracteres, números, puntos y el símbolo "/". Además de las comillas, el comando no puede contener "#" y no se permiten saltos de línea.

En el caso habitual en el que el argumento de la línea de comando contiene un solo ":", la secuencia de comando generalmente está asociada con alguna línea de descripción en el archivo MAKE que define las dependencias entre archivos. Si la línea relacionada con el objetivo especifica una secuencia de comandos, estos comandos se ejecutarán, incluso si el campo aommand después del punto y coma y (tab) puede incluso estar vacío si la línea relacionada con el objetivo no especifica un comando; luego se llamará el comando generado por el sistema. Reglas predeterminadas para los archivos de destino.

Si el argumento de la línea de comando contiene dos puntos ":::", la secuencia del comando puede estar relacionada con todas las líneas del archivo MAKE que describen las dependencias del archivo.

Se ejecutará el comando relacionado señalado por la línea descriptiva asociada con el objetivo. También se ejecutarán las reglas integradas.

Si el comando devuelve un error distinto de cero, como que el nombre del archivo de destino en el archivo MAKE es incorrecto o la cadena del comando usa un guión, la operación de creación generalmente finalizará, pero si el comando "-i "El parámetro se utiliza después del comando, make ignorará dichos errores.

El comando make en sí puede aceptar cuatro parámetros: indicadores, definiciones de macros, nombres de archivos de descripción y nombres de archivos de destino. El formato estándar es:

Crear [flags] [definiciones de macros] [objetivos]

La opción flags y su significado en sistemas Unix es:

-f El archivo especifica el archivo como un archivo de descripción. Si el parámetro del archivo es el carácter "-", el archivo de descripción apunta a la entrada estándar. Si no hay un parámetro "-f", el sistema utilizará de forma predeterminada el archivo denominado makefile o Makefile en el directorio actual como archivo de descripción.

En Linux, la herramienta GNU make buscará archivos MAKE en el directorio de trabajo actual en el orden GNUmakefile, makefile y Makefile.

-i Ignora los mensajes de error devueltos cuando se ejecuta el comando.

-s Modo silencioso, no se genera ninguna información de línea de comando correspondiente antes de la ejecución.

-r deshabilita las reglas integradas.

-n modo de no ejecución, genera todos los comandos ejecutados, pero no ejecuta estos comandos.

-t Actualiza el archivo de destino.

-q Dependiendo de si el archivo de destino se ha actualizado, la operación de creación devolverá información de estado "0" o no "0".

-p Muestra todas las definiciones de macros y descripciones de archivos de objetos.

-d modo de depuración, genera información detallada sobre el archivo y el tiempo de detección.

Las opciones comunes para el indicador make en Linux son ligeramente diferentes a las de Unix. Solo enumeramos las diferencias de la siguiente manera:

-c dir Antes de leer el archivo make, primero cambie a. el directorio de directorio especificado.

-I dir especifica el directorio donde buscar cuando se incluyen otros archivos MAKE que contienen esta opción.

-h Bloque de texto de ayuda que muestra todas las opciones de creación.

-w muestra el directorio de trabajo antes y después de procesar el archivo MAKE.

El objetivo en el parámetro de la línea de comando le permite especificar un objetivo de compilación para make y también le permite definir múltiples objetivos para la compilación simultánea y compilar los archivos de destino especificados en la opción de destino en orden de izquierda a derecha. a la derecha. Si no se especifica ningún objetivo en la línea de comando, el objetivo apuntará al primer objetivo en el archivo de descripción.

Por lo general, el archivo make también tiene un destino limpio, que se puede usar para eliminar archivos intermedios durante el proceso de compilación, por ejemplo:

clean:

rm -f *.o

Al ejecutar make clean, se ejecutará rm -f *.o, eliminando finalmente todos los archivos intermedios generados durante el proceso de compilación.

Cuando ejecute make clean, se ejecutará el comando rm -f *.o, que eventualmente eliminará todos los archivos intermedios generados durante el proceso de compilación.

Reglas implícitas

La utilidad make contiene una serie de reglas integradas o implícitas que definen cómo crear tipos específicos de objetivos a partir de diferentes archivos de dependencia. Los sistemas Unix generalmente admiten reglas implícitas basadas en extensiones de archivos, es decir, sufijos de nombres de archivos. o Archivo objeto

.cC archivo fuente

.fFORTRAN archivo fuente

.s ensamblado archivo fuente

.ySintaxis fuente Yacc-C

.lSintaxis fuente Lex

Los primeros sistemas Unix también soportaban la sintaxis fuente Yacc-C y la sintaxis fuente Lex. Durante el proceso de compilación, el sistema primero buscará el archivo .C relacionado con el archivo de destino en el archivo MAKE. Si hay archivos .y y .l que dependen del archivo, primero los convertirá en archivos .c y luego. compilar el archivo .o correspondiente; si no hay ningún archivo .c relacionado con el archivo de destino y solo el archivo .y relevante, el sistema compilará directamente el archivo .y.

Por otro lado, además de las reglas de sufijos, GNU make también admite otro tipo de reglas implícitas: reglas de patrones. Este tipo de regla es más versátil porque se pueden definir reglas de dependencia más complejas mediante reglas de patrón. Las reglas de patrón son muy similares a las reglas normales, excepto que hay un número adicional antes del nombre del archivo de destino, que se puede usar para definir la relación entre el archivo de destino y los archivos dependientes.

Por ejemplo, la siguiente regla de patrón define cómo convertir cualquier archivo file.c en un archivo file.o:

.c:.o

$(CC) $(CFLAGS) $ (CPPFLAGS) -c -o $@ $lt;

#EXAMPLE#

A continuación se muestra un ejemplo completo para ilustrar mejor la ejecución de archivos MAKE y comandos de creación, que implica más de solo archivos fuente C, que también involucran la sintaxis Yacc. Este ejemplo está tomado de las páginas 283-284 del "Manual del programador de Unix

, séptima edición, volumen 2A"

La siguiente es la documentación:

# Crear archivo de descripción del comando

#Enviar a imprimir

P=und -3 |p>

# Archivos fuente necesarios para los archivos objeto

FILES= Versión del archivo Make. c defs main.c donamc. c misc.c file.c \

dosys.c gram.y lex.c gcos.c

## Definición de archivo objeto

OBJECTS= vesion.o main.o donamc.o misc.o file.o dosys.o gram.o

LIBES= -LS

LINT= lnit -p

CFLAGS= -O

hacer: $(OBJECTS)

cc $(CFLAGS) $(OBJECTS) $(LIBES) -o hacer

tamaño make

$(OBJECTS): defs

gram.o: lex.c

limpieza:

- rm *.o gram.c

instalar:

@size make /usr/bin/ make

cp make /usr/bin/make;

#imprimir archivos modificados recientemente

imprimir: $(FILES)

pr $?| >

prueba:

make -dp | grep -v TIMEgt;1zap

/usr/bin/make -dp | grep -v TIMEgt;2zap

diff 1zap 2zap

rm 1zap 2zap

lint: dosys.c donamc.c archivo.c main.c misc.c versión.c gram.c

$(LINT) dosys.c donamc.c archivo.c main.c misc.c versión.c (

gram.c

rm gram.c

arch:

ar uv /sys/source/s2/make.a $(FILES)

Normalmente, la solicitud de salida para el comando que se va a ejecutar debe estar en el formato archivo de descripción Definición, como se indicó anteriormente.

Después de ejecutar el comando make, el resultado es:

$ make

cc -c version.c

cc -c main.c

cc -c donamc.c

cc -c misc.c

cc -c archivo.c

cc -c dosys.c

yacc gram.y

mv y.tab.c gram.c

cc -c gram.c

cc version.o main. o donamc .o misc.o file.o dosys.o gram.o \

-LS -o make

13188 3348 3044=19580b=046174b

Última entrada La información numérica es el resultado del comando "@size make". La razón por la que solo hay salida pero no hay una línea de comando correspondiente es porque el comando "@size make" comienza con "@", lo que prohíbe la impresión de la línea de comando donde se encuentra.

Las últimas líneas de comandos en el archivo de descripción son muy útiles para mantener la información de compilación. print "La línea de comando imprimirá todos los nombres de archivos que hayan cambiado desde la última vez que se ejecutó el comando "make print".

El sistema utiliza un archivo de 0 bytes llamado print para determinar el tiempo de ejecución de el comando de impresión. La macro $? Apunta al nombre del archivo modificado después de que se cambia el archivo de impresión. Si desea especificar que la salida se envíe al archivo especificado después de ejecutar el comando de impresión, puede modificar la definición de macro de P. :

make print "P= catgt;zap "

La mayor parte del software en Linux se proporciona en forma de código fuente en lugar de archivos ejecutables listos para usar. Esto requiere que los usuarios modifiquen el archivo. programa fuente de acuerdo con la situación real de su propio sistema y sus propias necesidades. Configure y compile antes de poder usar el software. Solo dominando la herramienta de creación podremos disfrutar realmente del mundo del software libre que nos ofrece Linux.