Este artículo no presenta cómo escribir un Makefile, pero comprende el enfoque de "capas basadas en objetivos" para comprender una herramienta, definir un diseño o implementar un conjunto de código.
Contenido:
Acerca de la compilación del programa
El principio de hacer un archivo de actualización
La sintaxis más básica de la regla Makefile es la siguiente
Acerca de la compilación del programa
Para explicar, Makefile se usó originalmente para resolver el problema de compilación del lenguaje C, por lo que tiene una relación muy estrecha con C, pero no significa que Makefile solo se pueda usar para resolver el problema de compilación de C. No tiene problemas para manejar Java, pero para Java, obviamente, Ant lo maneja mejor que Makefile. Pero esos son los detalles, si entiendes el Makefile, no hay dificultad para entender ant. El formato del propio Makefile no es estándar, y las diferentes herramientas de creación tienen diferentes detalles sobre cómo escribir el propio Makefile. Este artículo presenta la idea y el principio de esta herramienta, debe leer el manual correspondiente para obtener más detalles.
Makefile resuelve el problema de la compilación. ¿Qué tiene de malo compilar? Digamos, por ejemplo, que tiene 3 archivos C. Foo.c, bar.c, main.c son tres archivos C, si desea compilarlos en un app.exe, tendrá este comando:
De acuerdo con la práctica de los programadores de Unix, cualquier comando que se vuelva a ejecutar una y otra vez debe escribirse como un script y convertirse en "una acción". Por lo tanto, escribirá la secuencia de comandos anterior en un build.sh, y solo necesita ejecutar este script cada vez que compile, y el problema se resolverá.
Sin embargo, todavía hay un problema con este script, suponiendo que modifiqué foo.c, pero no modifiqué bar.c y main.c, entonces ejecutar este script es un desperdicio, porque volverá a compilar incondicionalmente bar.c y main.c .
Entonces, una forma más razonable de escribir este script debería ser así:
es complicado no? También de acuerdo con el estilo general de los programadores de Unix, si te enfrentas a un problema, no intentes redefinirlo, sino mira cuál es el problema adicional en comparación con el problema original e intenta resolver el problema adicional. Así que aquí, el problema adicional es la comparación del tiempo de modificación del archivo. Este es el problema básico que Makefile debe resolver. Definimos un nuevo "lenguaje de secuencias de comandos" (simplemente no interpretado por sh/bash/tch, sino por make) que se puede usar para ilustrar las comparaciones de archivos que necesitamos hacer de una manera muy simple. Entonces, el script anterior se puede escribir así:
Este es el problema original que resuelven los Makefiles. Makefile no es necesario, pero puede ahorrarle muchos problemas.
lPrincipio de funcionamiento de Makefile
La herramienta Make requiere un archivo llamado makefile para decirle a Make cómo trabajar. En general, un archivo MAKE le dice a Make cómo compilar y vincular un programa.
El principio de hacer un archivo de actualización:
a. Cada archivo fuente C modificado debe volver a compilarse
b. Si se modifica un archivo de encabezado, todos los archivos fuente C que contienen este archivo de encabezado deben volver a compilarse
c. Cada archivo fuente C se compila para generar un archivo objeto correspondiente (archivo obj, generalmente con el mismo nombre que el archivo fuente, con el sufijo .o)
d. Cada vez que se vuelve a compilar un archivo fuente C, todos los archivos de objeto deben volver a vincularse para producir un nuevo ejecutable
Es necesario comprender los cuatro principios anteriores. Cuando escribimos makefiles, debemos seguir los principios anteriores.
La sintaxis más básica de la regla Makefile es la siguiente:
Cada regla generalmente consta de uno o más objetivos (objetivo), requisitos previos (dependencia) y receta (prescripción). Cuando Make decide si ejecutar la receta en esta regla comparando el objetivo y los requisitos previos antiguos y nuevos, si los requisitos previos son más nuevos que la fecha de modificación del objetivo, la receta se ejecutará; de lo contrario, la receta en la regla no se ejecutará. ser ejecutado. Hay una cosa que vale la pena señalar: se debe agregar una pestaña antes de cada receta.
a. En la regla cuyo objetivo es editar, '' se usa para separar una línea larga en dos líneas para facilitar la lectura.
b. De forma predeterminada, Make comienza a ejecutarse desde la primera regla de Makefile por defecto, es decir, cuando solo escribimos "make" en el shell y presionamos Enter, make automáticamente direccionará el Makefile en el directorio actual y comenzará desde La primera de estas reglas comienza a ejecutarse. Por supuesto, también podemos especificar las reglas para empezar a ejecutar
Ejemplo: make clean //Iniciar la ejecución desde la regla cuyo destino es clean
c. Cuando la primera edición de la regla comience a ejecutarse de forma predeterminada, dado que el objetivo depende de algunos archivos .o, y estos archivos .o tienen sus propias reglas de actualización, primero activará la ejecución de las propias reglas de actualización del archivo .o, y finalmente volver a ejecutar editar. Puedes pensar en ello como un proceso recursivo.
d. Obviamente, dado que el objetivo de clean no depende de ningún otro objetivo y no es el objetivo de la primera regla, a menos que se especifique que se comience con esta regla, esta regla nunca se ejecutará; Una regla no tiene dependencias y la ejecución de esta regla nunca desencadenará la ejecución de otras reglas.
Las reglas son una parte importante de Makefile y Make decide cómo actualizar los archivos del proyecto al leer las reglas en Makefile. En general, una regla se divide en tres partes: objetivo, requisitos previos y receta.
Si no especifica qué regla ejecutar, Make siempre ejecuta la primera regla en el archivo. Además, el orden de escritura de otras reglas no tiene efecto en el orden de ejecución (Make solo ejecuta las reglas requeridas cuando es necesario. , en lugar que en el orden de escritura).
Aunque la primera regla en el Makefile es la primera en ejecutarse, a menudo es la última en ejecutarse, porque la parte de dependencia en la primera regla a menudo tiene sus propias reglas de actualización, y las dependencias en las reglas de actualización tienen reglas de actualización correspondientes, recursivamente, la primera regla desencadena la ejecución de otras reglas y, una vez que se ejecutan las otras reglas, vuelve a la primera regla para continuar con la ejecución. Lo mismo es cierto cuando compilamos un programa. Siempre compilamos cada subarchivo primero y luego los conectamos de nuevo para formar un programa. Por lo tanto, la primera regla en el Makefile generalmente se usa para desencadenar la compilación de todo el programa (y la primera El objetivo de una regla generalmente se llama: todo, lo que significa actualizar todo el proyecto)
En la regla, puede usar '$' para llamar a la variable definida (si realmente desea escribir un '$' en lugar de una referencia de variable, debe escribir "$$".
Cada regla tiene sus propias recetas, que constan de una o más instrucciones de shell y se ejecutan en el orden en que se escriben. Por lo general, el resultado de la ejecución es actualizar el objetivo. De forma predeterminada, se llama a /bin/sh para ejecutar el comando de shell, que se puede cambiar manualmente.
Es decir, hay instrucciones de shell y declaraciones propias del archivo MAKE en el archivo MAKE, por lo que el archivo MAKE sigue dos sintaxis: use la sintaxis del shell en las recetas y siga la sintaxis del archivo MAKE en otras partes. make solo realiza un procesamiento limitado de las recetas en el archivo MAKE y luego las arroja al shell para su ejecución.
Cosas a tener en cuenta al escribir recetas:
a. Cada receta generalmente comienza con caracteres [TAB], por supuesto que hay otras formas de escribir, pero creo que esto es suficiente por ahora
b. Una línea en blanco que comienza con [TAB] también es una receta, llamada receta vacía
c. El contenido después de '#' en la receta no se usará como comentario, pero se pasará intacto al shell
d. A partir de [TAB], las variables definidas en la receta también se pasarán al shell como variables de shell intactas, no como variables en el archivo MAKE.