Primeros pasos con Makefile fácil de entender (01): qué es Makefile, por qué usar Makefile, reglas de Makefile y cómo lograr una compilación incremental en el proceso de Makefile

1. ¿Qué es Makefile?

MakefileEl documento describe Linuxlas C/C++reglas de compilación del sistema del proyecto, que se utiliza para compilar el C/C++proyecto de automatización . Una vez que la escritura es buena escribiendo Makefilepapeles, solo un makecomando, todo el proyecto comenzará a compilarse automáticamente, ya no es necesario ejecutar manualmente GCCel comando. En un gran C/C++archivo fuente del proyecto hay cientos, según sus funciones, módulos, tipos se colocaron en diferentes directorios, el Makefilearchivo define un conjunto de reglas que indica el orden de compilación de las dependencias del archivo fuente, la necesidad de volver a compilar y pronto.

MakefilePuede considerarse simplemente como las reglas de compilación de un archivo de proyecto, que describen las reglas de compilación y vinculación de todo el proyecto. Que contiene los archivos que deben compilarse, los archivos que no necesitan compilarse, los archivos que deben compilarse primero, los archivos que deben compilarse más tarde, los archivos que deben reconstruirse, etc. Recopile todas las necesidades del proyecto involucradas, en Makefileambas se pueden describir. En otras palabras, Makefilela compilación de nuestro proyecto se puede automatizar sin tener que ingresar manualmente un montón de archivos fuente y parámetros cada vez.

2. Por qué utilizar Makefile

Para Linuxreducir el Cdesarrollo del lenguaje como ejemplo para explicar el compilador de múltiples archivos específico que genera un archivo, el comando del compilador es el siguiente:

gcc -o outfile name1.c name2.c ...

outfileEl nombre del programa ejecutable que se generará es el nombre nameN.cdel archivo fuente. Esto es lo que Linuxusamos en el gcccompilador para compilar Clos archivos de muestra. Si el número de archivos fuente que encontramos no es muy grande, podemos elegir este método de compilación. Si hay demasiados archivos fuente, encontrará los siguientes problemas.

2.1 El problema de vincular bibliotecas al compilar

Aquí hay algunas bibliotecas estándar que debemos vincular manualmente:

  • name1.cUtiliza mathfunciones de biblioteca matemática , tenemos que agregar parámetros manualmente -lm;
  • name4.cUse una SQLitefunción de base de datos pequeña , tenemos que agregar parámetros manualmente -lsqlite3;
  • name5.cCuando se utilizan subprocesos, necesitamos agregar parámetros manualmente -lpthread;

Debido a que hay muchos archivos, se deben vincular muchas bibliotecas de terceros. Por lo tanto, el comando será muy largo al compilar y es posible que estemos involucrados en el orden de vinculación de archivos al compilar, por lo que la compilación manual será muy problemática.

Si aprendemos a usar Makefileno el caso, simplificaría radicalmente el funcionamiento del compilador. Para vincular el archivo de la biblioteca Makefile, el desarrollo de las reglas apropiadas y el orden de enlace correspondiente. Así que solo necesita ejecutar makeel comando, el proyecto compilará automáticamente una compilación manual de opciones de parámetros y comandos omitidos, muy conveniente.

2.2 La compilación de un proyecto grande llevará mucho tiempo

MakefileLa compatibilidad con la operación simultánea de múltiples subprocesos acortará en gran medida nuestro tiempo de compilación, y cuando modifiquemos el archivo fuente, al compilar todo el proyecto, el makecomando solo compilará los archivos que hemos modificado y los archivos no modificados no necesitan volver a compilarse. Resolvió nuestro problema que consumía mucho tiempo.

Y el archivo Makefilesolo debe hacerse una vez, generalmente no agregamos un archivo o eliminamos el proyecto, Makefilebásicamente no tenemos que modificarlo, en tiempo de compilación use solo un makecomando. Nos proporciona una gran comodidad y mejora en gran medida la eficiencia de la compilación.

3. Reglas de Makefile

Sus reglas se componen principalmente de dos partes, la relación de dependencia y el comando ejecutado, y su estructura es la siguiente:

targets : prerequisites
    command

o

targets : prerequisites; command
    command

Las instrucciones relevantes son las siguientes:

  • targets: El objetivo de la regla es imprescindible, puede ser Object File(generalmente llamado archivo intermedio), puede ser un archivo ejecutable o puede ser una etiqueta;
  • prerequisites: Nuestro archivo de dependencia para generar targetsun archivo o un objetivo deseado. Puede haber varios, separados por espacios o ninguno;
  • command: makeComando (debe ejecutar cualquiera de los shellcomandos). Puede haber varios comandos, cada comando ocupa una línea;

Si es commanddemasiado largo, puede utilizar \una nueva línea.

Nota: Para usar dos puntos entre nuestros objetivos y los archivos dependientes están separados, el comando de inicio debe usar las Tabteclas, no puede usar la barra espaciadora.

Para resumir brevemente Makefileel contenido, contiene principalmente cinco partes, a saber:

3.1 Reglas explícitas

Las reglas explícitas explican cómo generar uno o más archivos de objeto. Esto se debe a que Makefilelos escritores señalaron claramente que el archivo resultante, las dependencias del archivo, generaron comandos.

3.2 Reglas oscuras

Como nuestro makenombre con función de derivación automática, las reglas tan oscuras nos permiten escribir brevemente terreno irregular Makefile, que es un makecomando compatible.

3.3 Definición de variables

En el Makefilemedio tenemos que definir un conjunto de variables, que generalmente son cadenas, esto es un poco como las macros del lenguaje C, cuando se Makefileejecutan, donde las variables se extenderán a la posición de referencia correspondiente.

3.4 Documentar instrucciones

Que consta de tres partes, una es una Makefilereferencia a la otra Makefile, como en el lenguaje C includecomo; se refiere a los otros casos de acuerdo con cierta Makefileporción válida especificada , como lenguaje C precompilado #iflo mismo; y Es para definir un comando multilínea .

3.5 Notas

MakefileSólo en línea comentarios, y UNIXde Shelllos mismos scripts que el comentario es #caracteres, si desea que su Makefileuso de #caracteres puede ser con una barra invertida, tales como: \#.

3.6 comodines en las reglas

  • * Representa uno o más caracteres
  • ? Representa cualquier personaje
  • [...] [abcd] significa cualquier carácter en a, b, c, d, [^ abcd] significa un carácter que no sea a, b, c, d, [0-9] significa cualquier número del 0 al 9
  • ~ Representa el directorio de inicio del usuario

4.Ejemplo de Makefile

main.cpp Código:

#include <iostream>

int main()
{
    
    
    std::cout << "hello,world" << std::endl;
    return 0;
}

Específicamente mediante los siguientes ejemplos sobre el uso del archivo de Makefilereglas Makefile, agregue el siguiente código:

main: main.cpp
	g++ main.cpp -o main

Cuál maines el archivo de destino y nuestro archivo ejecutable resultante. Archivos dependientes que main.cppoperan con los archivos de origen, los archivos de objetos deben hacer para reconstruirlos g++ main.cpp -o main. Este es el Makefileuso de reglas gramaticales básicas.

Modo de uso Makefile: primero debe escribir un buen Makefilearchivo y luego ejecutar el makecomando de shell , el programa se ejecutará automáticamente y obtendrá el archivo de destino final.

wohu@ubuntu:~/cpp/demo$ ls
main.cpp  `Makefile`
wohu@ubuntu:~/cpp/demo$ make 
g++ main.cpp -o main
wohu@ubuntu:~/cpp/demo$ ls
main  main.cpp  `Makefile`
wohu@ubuntu:~/cpp/demo$ ./main 
hello,world
wohu@ubuntu:~/cpp/demo$ 

Si se usa la barra espaciadora al comienzo del comando, se informará un error

Makefile:2: *** missing separator.  Stop.

Makefile: 2 para el error de la segunda línea, debería Tabcomenzar.

5. Proceso de Makefile

Cuando ejecutamos makecuando el comando, makese realizará para buscar compilar las reglas bajo el archivo actual, que es Makefilearchivo. Escribimos el Makefilenombre del archivo cuando se puede usar GNUMakefile, makefile, Makefile, makepara volver a buscar a la hora de realizar Makefilearchivo, busque la secuencia de archivo es como esto.

Recomendado de usar Makefile(generalmente escrito de esta manera en el proyecto, las mayúsculas estarán más estandarizadas). Si el archivo no existe, makese nos informará de un error, solicitando:

make: *** No targets specified and no `Makefile` found.  Stop.

Al Makefileagregar el siguiente código:

main: main.o   name.o greeting.o
	g++ main.o name.o greeting.o -o main
main.o: main.cpp
	g++ -c main.cpp -o main.o
name.o: name.cpp
	g++ -c name.cpp -o name.o
greeting.o: greeting.cpp
	g++ -c greeting.cpp -o greeting.o

Cuando compilamos el archivo del proyecto, por defecto, la makeejecución es la Makefileprimera regla ( Makefileaparecen las primeras dependencias), el primer objetivo de esta regla se denomina "objetivo final" o "objetivo final".

En la shelllínea de comandos del makesistema, puede obtener los archivos ejecutables mainy archivos intermedios main.o, name.oy greeting.o, mainque es nuestro documento final que será generada.

Por Makefilepuede encontrar nuestro objetivo mainen Makefileel primer gol, por lo que es el makeobjetivo final, cuando la modificación de los archivos, ejecutar makereconstruirá el objetivo final main.

Su orden de trabajo específica es: cuando shellla entrada solicita el makecomando subsiguiente. makeLeer en los Makefilearchivos del directorio actual , y Makefilearchivar el primer objetivo como "objetivo final" de su ejecución, comenzar a procesar la primera regla (regla donde el objetivo final).

En nuestro ejemplo, la primera regla es el objetivo de mainlas reglas se encuentra. Las reglas describen las maindependencias y definen el comando de .odestino de generación de archivos de enlace main; makeantes de ejecutar este comando, las reglas definidas por el primer destino de procesamiento, maintodos los archivos dependientes (esos ejemplos del .oarchivo) actualizan la regla (estos .oarchivos Reglas de destino).

Estas .oreglas de segmentación se refieren al archivo de los siguientes tres casos:

  • El .oarchivo de destino no existe, créelo usando sus reglas de descripción;
  • El .oarchivo de destino existe, el .oarchivo de destino depende del archivo ".cpp" fuente ".h" de cualquier archivo de .o"Actualización" de proporción de destino (última marca después de ser modificado), luego se vuelven a compilar las reglas según las cuales;
  • El .oarchivo de destino existe, el .oarchivo de destino que cualquiera de sus dependencias (".c" fuente, ". H" archivo) "Actualizar" (Depende de que el archivo no se haya modificado después de una renovación), no haga nada ;

A través de las reglas de actualización anteriores podemos entender el rol del archivo intermedio, que se genera al compilar .oel archivo. La función es comprobar si se ha modificado un determinado archivo de origen y si es necesario reconstruir el archivo de destino final.

Ejecutamos el makecomando, solo se reconstruirán los archivos de origen modificados o el archivo de destino inexistente, pero esos archivos no se cambian sin volver a compilar, para ahorrar tiempo en gran parte, para mejorar la eficiencia de la programación.

Supongo que te gusta

Origin blog.csdn.net/wohu1104/article/details/110905996
Recomendado
Clasificación