[Desarrollo de Linux: herramienta Makefile]

1. Antecedentes

  • Un proyecto suele tener varios archivos fuente. Si solo modifica uno de ellos, sería una pérdida de tiempo volver a compilar y vincular todos los archivos fuente. Por lo tanto, es muy necesario presentar la herramienta Makefile: la herramienta Makefile puede encontrar automáticamente los archivos fuente que deben recompilarse y vincularse en función de las dependencias del archivo, y realizar las acciones correspondientes en ellos.

Dos, comprensión

1, crea un archivo MAKE

  • Makefile define una serie de reglas para especificar qué archivos deben compilarse primero, qué archivos deben compilarse más tarde, qué archivos deben compilarse nuevamente y operaciones funcionales aún más complejas, porque el archivo MAKE es como un script de Shell, que también puede ser ejecutados Comandos del sistema operativo.
  • La función más importante y básica de la herramienta Make es describir la relación entre los programas fuente a través de archivos MAKE y mantener automáticamente el trabajo de compilación .
  • El archivo MAKE debe escribirse de acuerdo con una sintaxis determinada, el archivo debe explicar cómo compilar cada archivo fuente y conectarlo para generar un archivo ejecutable, y es necesario definir las dependencias entre los archivos fuente.
  • Los archivos Makefile son un método común utilizado por muchos compiladores, incluidos los compiladores de Windows, para mantener la información de compilación. En el entorno de desarrollo integrado, los usuarios solo modifican los archivos Makefile a través de una interfaz amigable.
  • En los sistemas UNIX, es habitual utilizar Makefile como archivo Makefile. Si desea utilizar otro archivo como archivo MAKE, puede especificar el archivo MAKE usando opciones de comando make similares.
  • Un archivo que indica a un programa cómo compilar y vincular el programa. El nombre predeterminado del archivo MAKE es literalmente Makefile, pero se puede especificar un nombre de opción de línea de comando.
  • El programa make le ayuda cuando desarrolla programas grandes a realizar un seguimiento de todo el programa, partes del cual han cambiado, y solo aquellas partes del programa compiladas desde la última vez que se compiló.

2. Acerca de la compilación

La compilación de un pequeño programa en C requiere al menos un único archivo .h (si corresponde). Aunque el comando para realizar esta tarea es simplemente CC file.c, existen 3 pasos para obtener el programa ejecutable final de la siguiente manera:

  • Fase de compilación : todo el código de lenguaje C en el archivo .c se convierte a un lenguaje ensamblador de bajo nivel, creando el archivo .s.

  • Etapa de ensamblaje : el código en lenguaje ensamblador creado en la etapa anterior se convierte en fragmentos de código de destino que la computadora puede comprender directamente. El archivo de código objeto .o finaliza.

  • Fase de vinculación : la fase final del proceso de compilación implica vincular el código objeto al código base, que contiene ciertas funciones "integradas" como printf. Esta etapa produce un programa ejecutable, que por defecto se denomina a.out.

3. Caso de compilación:

Suponga los siguientes archivos fuente.

main.cpp
hello.cpp
factorial.cpp
functions.h
  • Contenido del archivo main.cpp
#include <iostream.h>

#include "functions.h"

int main(){
    
    
    print_hello();
    cout << endl;
    cout << "The factorial of 5 is " << factorial(5) << endl;
    return 0;
}
  • Contenido del archivo hello.cpp
#include <iostream.h>

#include "functions.h"

void print_hello(){
    
    
   cout << "Hello World!";
}
  • Contenido del archivo factorial.cpp
#include "functions.h"

int factorial(int n){
    
    
    if(n!=1){
    
    
	return(n * factorial(n-1));
    }
    else return 1;
}
  • contenido de funciones.h
void print_hello();
int factorial(int n);

Una forma trivial de compilar el archivo y obtener un ejecutable ejecutando el siguiente comando:

CC  main.cpp hello.cpp factorial.cpp -o hello
  • CC: significa compilador (gcc), compila archivos C++,
  • El comando anterior generará un saludo binario. En nuestro caso solo tenemos cuatro archivos y conocemos la secuencia de llamadas a funciones, por lo que podría ser factible escribir los comandos anteriores a mano y preparar el binario final. Pero para proyectos grandes, donde tendremos miles de archivos de código fuente, será difícil mantener versiones binarias.
  • El comando make le permite administrar programas grandes o grupos de programas . Cuando comience a escribir programas más grandes, encontrará que recompilar programas más grandes lleva más tiempo que recompilar programas cortos. Por lo general, también se encuentra solo una pequeña parte del programa (como una única función que se está depurando), dejando el resto del programa sin cambios.

3. Macro de archivo Make

El programa make le permite utilizar macros, que son similares a las variables. = Un par de macros definidas en un Makefile. Por ejemplo:

MACROS=  -me
PSROFF=  groff -Tps
DITROFF= groff -Tdvi
CFLAGS= -O -systype bsd43
LIBS := "-lncurses -lm -lsdl"
LIBS += -lstdc++
MYFACE = ":*)"
PROJ_HOME = /home/moon/projects
$(MACROS)
$(MYFACE) :*)

1. Macros especiales ( $@, $?, $<, $*, $^)

1, $@,$?

Hay algunas macros especiales predefinidas antes de emitir cualquier comando al conjunto de reglas de destino.
- $@representa el archivo de destino.
-Indica una lista de archivos dependientes que son más recientes$? que el objetivo .

Así, por ejemplo, podríamos utilizar una regla:

hello: main.cpp hello.cpp factorial.cpp
	$(CC) $(CFLAGS) $? $(LDFLAGS) -o $@

alternatively:

hello: main.cpp hello.cpp factorial.cpp
        $(CC) $(CFLAGS) $@.cpp $(LDFLAGS) -o $@
  • En este ejemplo $@ representa hola, ? o ? o? o @.cpp recogerá todos los archivos fuente modificados.

2, $<,$*

Hay dos macros especiales que se utilizan en reglas implícitas. Ellos son:

  • $<Representa el primer archivo dependiente .
  • $*Esta variable representa el "%" y la parte anterior en el patrón de destino . .oarchivo equivalente a %.oarchivo
    • Porque $*si el objetivo es "dir/a.foo.b" y el modo del objetivo es "a.%.b", entonces $*el valor de " " es "dir/a.foo". Esta variable es útil para construir nombres de archivos asociados. Si no hay una definición de patrón en el destino, entonces " $*" no se puede deducir. Sin embargo, si make reconoce el sufijo del archivo de destino, entonces " $*" es la parte excepto el sufijo. Por ejemplo: si el objetivo es "foo.c", porque ".c" es un nombre de sufijo reconocido por make, $*el valor de " " es "foo". 这个特性是GNU make的,很有可能不兼容于其它版本的make, por lo que debes intentar evitar el uso de " $*" a menos que sea en reglas implícitas o en modo estático. Si make no reconoce el sufijo en el destino, entonces " $*" es un valor nulo. .
      Se construyen reglas implícitas comunes para archivos .o (objeto), .cpp (archivos fuente).
.o:.cpp
        $(CC) $(CFLAGS) -c $<

alternatively

.o:.cpp
        $(CC) $(CFLAGS) -c $*.cpp

3,$^

$^Mostrar todas las dependencias:

LDFLAGS = -lstdc++
hello:main.o factorial.o hello.o
	$(CC) $^ $(LDFLAGS ) -o $@

2. Macro tradicional

Hay muchas macros predeterminadas (al escribir " make -p " se imprimen las predeterminadas). La mayoría de las reglas para su uso son obvias:
estas variables predefinidas, es decir. Las macros utilizadas en reglas implícitas se dividen en dos categorías amplias: aquellas con nombres de programas (como CC) y aquellas con parámetros (como CFLAGS).

A continuación se muestra una tabla de algunas de las variables más comunes utilizadas como reglas integradas: nombres de programas de archivos MAKE.

  • Programa de mantenimiento de archivos AR ; por defecto 'ar'.
  • AS Programa para compilar archivos de ensamblaje; predeterminado "como".
  • Programa CC para compilar programas C; predeterminado 'cc'.
  • Programa CO para retirar archivos de RCS; predeterminado 'co'.
  • CXX Programa para compilar programas C++; predeterminado `g++'.
  • CPP Programa para ejecutar el preprocesador C, con resultados a salida estándar; predeterminado `$(CC) -E'.
  • Programa FC para compilar o preprocesar programas Fortran y Ratfor; predeterminado 'f77'.
  • GET Programa para extraer un archivo de SCCS; predeterminado 'obtener'.
  • Programa LEX que se utilizará para convertir gramáticas Lex en código fuente; predeterminado `lex'.
  • Programa YACC a utilizar para convertir gramáticas de Yacc en código fuente; predeterminado 'yacc'.
  • LINT Programa a utilizar para ejecutar lint en el código fuente; `pelusa' predeterminada.
  • Programa M2C que se utilizará para compilar el código fuente de Modula-2; predeterminado 'm2c'.
  • Programa de PC para compilar programas Pascal; 'pc' predeterminado.
  • MAKEINFO Programa para convertir un archivo fuente Texinfo en un archivo Info; predeterminado `makeinfo'.
  • Programa TEX para crear archivos TeX dvi a partir de fuente TeX; `tex' predeterminado.
  • TEXI2DVI Programa para crear archivos TeX dvi a partir de la fuente Texinfo; predeterminado `texi2dvi'.
  • Programa WEAVE para traducir Web a TeX; "tejido" predeterminado.
  • Programa CWEAVE para traducir C Web a TeX; `cweave' predeterminado.
  • TANGLE Programa para traducir Web a Pascal; 'enredo' predeterminado.
  • CTANGLE Programa para traducir C Web a C; `rectángulo' predeterminado.
  • Comando RM para eliminar un archivo; predeterminado `rm -f'.

Aquí hay una variable cuyo valor es una lista de parámetros adicionales para el programa anterior. El valor predeterminado para todos estos es la cadena vacía a menos que se especifique lo contrario.

  • ARFLAGS Banderas para dar el programa de mantenimiento de archivos; predeterminado `rv'.
  • ASFLAGS Indicadores adicionales para entregar al ensamblador (cuando se invocan explícitamente en un .s' or archivo .S).
  • CFLAGS Indicadores adicionales para entregar al compilador de C.
  • CXXFLAGS Indicadores adicionales para entregar al compilador de C.
  • COFLAGS Banderas adicionales para regalar al programa RCS co.
  • CPPFLAGS Banderas adicionales para darle al preprocesador de C y a los programas que lo usan (los compiladores de C y Fortran).
  • FFLAGS Indicadores adicionales para entregar al compilador de Fortran.
  • GFLAGS Banderas adicionales para entregar al programa de obtención de SCCS.
  • LDFLAGS Banderas adicionales para dar a los compiladores cuando se supone que deben invocar el enlazador, `ld'.
  • LFLAGS Banderas extra para dárselas a Lex.
  • YFLAGS Banderas extra para regalar a Yacc.
  • PFLAGS Indicadores adicionales para entregar al compilador Pascal.
  • RFLAGS Indicadores adicionales para entregar al compilador Fortran para programas Ratfor.
  • LINTFLAGS Banderas adicionales para eliminar la pelusa.

Nota: Puede desmarcar -Ru --no-builtin-variablesoptar por todas las variables utilizadas por la regla implícita.
Por ejemplo, también puede definir macros en la línea de comando

          make CPP=/home/moon/projects

4. Makefile define dependencias

新版的gcc编译器引入头文件不再需要后缀名,eg:# include<iostream>,不再需要.h后缀。

Es muy común que el binario final dependa de varios códigos fuente y archivos de encabezado del código fuente. Las dependencias son importantes porque indican el origen de cualquier objetivo. Por favor vea el ejemplo a continuación

hello: main.o factorial.o hello.o
	$(CC) main.o factorial.o hello.o -o hello
  • Aquí, le decimos al archivo objeto hola que depende de main.o, factorial.o y hello.o, por lo que cada vez que haya algún cambio, estos archivos objeto tomarán medidas. También puede usar la regla de compilación: en su $(CC) $? -o $@lugar $(CC) main.o factorial.o hello.o -o hello.

Al mismo tiempo diremos cómo preparar el archivo .o, por lo que debemos definir estas dependencias también de la siguiente manera:

main.o: main.cpp functions.h
	$(CC) -c main.cpp

factorial.o: factorial.cpp functions.h
	$(CC) -c factorial.cpp

hello.o: hello.cpp functions.h
	$(CC) -c hello.cpp

Si hay muchas dependencias, use += en LDFLAGS para conectarse
Insertar descripción de la imagen aquí

5. Reglas de definición de Makefile

Sintaxis general de una regla de destino Makefile

    target [target...] : [dependent ....]
    [ command ...]
  • Los elementos entre corchetes son opcionales y las elipses se refieren a uno o más. Tenga en cuenta la etiqueta, requerida antes de cada comando.

A continuación se muestra un ejemplo simple que define una regla que hace que su objetivo salude desde otros tres archivos.

hello: main.o factorial.o hello.o
	$(CC) $? -o $@
  • NOTA: En este ejemplo, debe eliminar la regla para que todos los objetos lean el archivo desde el archivo fuente.

La semántica es bastante simple. Cuando "make target" descubre que se aplican las reglas del objetivo, si hay un nuevo objetivo dependiente, hace que los comandos se ejecuten uno a la vez (después de la sustitución de la macro). Si se produce alguna dependencia, eso sucede primero (lo que le permite tener una recursividad).
Si algún comando devuelve un estado de falla, MAKE terminará. Por eso ves reglas como:

clean:hello
        -rm *.o *~ core paper
  • Make ignora el estado devuelto por una línea de comando que comienza con un guión. Por ejemplo. Si no hay archivos centrales, ¿a quién le importa? , después de definir clean, ejecute: make clean, limpie todos los archivos

Make hará eco de la cadena de macro después del comando de reemplazo, contando lo que sucedió tal como sucedió. A veces es posible que desees desactivarlos. Por ejemplo:

install:hello
        @echo You must be root to install
  • @ se agrega antes del comando echo para indicar una salida silenciosa y no imprimirá nada que no esté relacionado con la información. Por ejemplo, echo no se imprimirá, pero debe ser root para instalar.
  • Algunos de los objetivos de Makefiles que todo el mundo espera. Siempre debes navegar primero, pero está razonablemente pensado para apuntar (o simplemente hacer), instalar y limpiar.
    • make all: compila todo para que puedas probar localmente, las cosas previamente instaladas, todas se pueden usar junto con reglas, por ejemplo:all:hello install
    • make install: cosas que deben instalarse en el lugar correcto. Pero parece que todo está instalado en el lugar correcto para el sistema.
    • limpiar - algo que debe limpiarse. Deshágase del archivo ejecutable, cualquier archivo temporal, archivo objeto, etc.

6. Reglas implícitas de Makefile

1. El comando debe usarse en todos los casos en los que construyamos un ejecutable x con el código fuente x.cpp como regla implícita, que se puede decir:

.cpp:
        $(CC) $(CFLAGS) $@.cpp $(LDFLAGS) -o $@
  • Esta regla implícita dice que si make c, xc ejecuta la llamada xc y genera x. Las reglas están implícitas porque no se menciona ningún objetivo específico. Se puede utilizar en todas las situaciones.

2. Otra regla implícita común es la construcción de archivos .o (objeto) y .cpp (archivos fuente).

.o:.cpp
        $(CC) $(CFLAGS) -c $<

alternatively

.o:.cpp
        $(CC) $(CFLAGS) -c $*.cpp

3. $^ indica todas las dependencias

#LDFLAGS 表示依赖库
LDFLAGS = -lstdc++ 
hello:main.o factorial.o hello.o
        $(CC) $^ $(LDFLAGS) -o $@
.o:.cpp functions.h
        $(CC) -c $<
clean:
        -rm *.o hello
install:hello
        @echo "You need build hello!"
        echo "no @ used"
all:hello install

7. Reglas de sufijo personalizadas de Makefile

Por su parte, make ya sabe que para crear un archivo .o debe usar cc-c el archivo c correspondiente. Estas reglas integradas en MAKE pueden aprovechar esto para acortar el Makefile. Si una línea de dependencia de Makefile simplemente representa un archivo .h del que depende el objetivo actual, MAKE sabrá que se ha especificado el archivo correspondiente. Ni siquiera necesitas el comando de inclusión del compilador.
Esto reduce nuestro Makefile aún más a lo siguiente:

OBJECTS = main.o hello.o factorial.o
hello: $(OBJECTS)
        cc $(OBJECTS) -o hello
hello.o: functions.h
main.o: functions.h 
factorial.o: functions.h 

1. .SUFFIXESPermitir sufijos personalizados

Make utiliza un objetivo especial, de ahí el nombre, que .SUFFIXESle permite definir sus propios sufijos . Por ejemplo, dependencias:

.SUFFIXES: .foo .bar
  • Dile a make que estos sufijos especiales se utilizarán para crear tus propias reglas.

Cómo hacer que make ya sepa cómo generar archivos .o a partir de archivos .c. De manera similar, las reglas se pueden definir de la siguiente manera:

.foo:.bar
        tr '[A-Z][a-z]' '[N-Z][A-M][n-z][a-m]' < $< > $@
.c:.o
        $(CC) $(CFLAGS) -c $<
  • La primera regla le permite crear un archivo .bar a partir de un archivo .foo. (no te preocupes por lo que hace, básicamente codifica el archivo)
  • El segundo archivo de reglas .c crea un archivo .o usando las reglas predeterminadas.

2, *es un comodín

*Se utiliza para representar palabras arbitrarias, lo que puede simplificar enormemente el archivo MAKE:

LDFLAGS = -lstdc++

all:hello install

hello:*.cpp *.h
        $(CC) $^ $(LDFLAGS) -o $@

clean:
        -rm *.o hello

install:hello
        @echo "You need build hello!"
        echo "no @ used"

8. Instrucciones del archivo Make

Hay varias instrucciones en diferentes formas. Es posible que el programa no admita todos los comandos. Por lo tanto, verifique si make admite la directiva; aquí exploramos algunas de las directivas admitidas por GNU make.

1. Instrucciones condicionales

Instrucciones condicionales:

  • La condición para iniciar la instrucción ifeq , la condición especificada. Contiene dos parámetros separados por comas y entre paréntesis. La sustitución de variables se realiza en los dos parámetros y luego se comparan. La línea en el archivo MAKE que sigue a IFEQ se obedece si los dos parámetros coinciden; de lo contrario, se ignora. ¿Son iguales?
  • La condición para iniciar la instrucción ifneq , la condición especificada. Contiene dos parámetros separados por comas y entre paréntesis. La sustitución de variables se realiza en los dos parámetros y luego se comparan. makefile respeta ifneq si los dos argumentos no coinciden, de lo contrario se ignoran. no espera
  • La condición para iniciar la directiva ifdef , la condición especificada. Contiene un único parámetro. La condición es verdadera si los argumentos dados son verdaderos. ¿Está definido?
  • La condición para iniciar la directiva ifndef , la condición especificada. Contiene un único parámetro. Si lo dado es falso, entonces la condición es verdadera. ¿Está indefinido?
  • La directiva else dará como resultado la siguiente línea si no se respeta la condición anterior. En el ejemplo anterior, esto significa que la segunda opción para conectarse al comando no se usa cuando se usa la primera opción. Es opcional y tiene un else if condicional.
  • La condición final de la directiva endif . Cada condición debe terminar con endif.

1. Sintaxis de instrucciones condicionales

Un condicional simple sin
otra sintaxis es el siguiente:

conditional-directive
text-if-true
[else
text-if-false]
endif
  • texto si es verdadero puede ser cualquier línea de texto que se considere parte del archivo MAKE si la condición es verdadera. Si la condición es falsa, no se sustituye ningún texto.
  • Los corchetes []indican que se ignora el contenido correspondiente.

La sintaxis de una condición compleja
es la siguiente:

conditional-directive
text-if-true
else
text-if-false
endif
  • Si la condición es verdadera, se usa el texto si es verdadero; de lo contrario, si se usa el texto falso en su lugar. El texto, si el número de errores, puede ser cualquier línea de texto.

La sintaxis de las directivas condicionales es la misma ya sea que la condición sea simple o compleja. Hay cuatro instrucciones diferentes para probar diferentes condiciones .
Aquí hay una tabla:

ifeq (arg1, arg2)
ifeq 'arg1' 'arg2'
ifeq "arg1" "arg2"
ifeq "arg1" 'arg2'
ifeq 'arg1' "arg2" 

Las instrucciones opuestas a las condiciones anteriores son las siguientes:

ifneq (arg1, arg2)
ifneq 'arg1' 'arg2'
ifneq "arg1" "arg2"
ifneq "arg1" 'arg2'
ifneq 'arg1' "arg2" 

2. Ejemplo de instrucciones condicionales

Instrucciones condicionales, compilación multiplataforma.

libs_for_gcc = -lgnu
normal_libs =

foo: $(objects)
ifeq ($(CC),gcc)
        $(CC) -o foo $(objects) $(libs_for_gcc)
else
        $(CC) -o foo $(objects) $(normal_libs)
endif

2. incluir directiva

La directiva de inclusión le dice a make que detenga la lectura del archivo MAKE actual y lea uno o más archivos MAKE antes de continuar. La directiva es una sola línea en el archivo MAKE y tiene este aspecto:

include filenames...

Los nombres de archivos pueden contener patrones de nombres de archivos de shell. Se permiten espacios adicionales al principio de la línea que se ignorarán, pero no se permite una etiqueta. Por ejemplo, si hay tres .mk'文件, a.mk', b.mk', and c.mk' y $(bar) expandidos en bash, entonces aparece la siguiente expresión.

include foo *.mk $(bar)

is equivalent to

include foo a.mk b.mk c.mk bash

Cuando MAKE procesa la directiva de inclusión, detiene la lectura del archivo MAKE que lo contiene y lee cada archivo enumerado por turno. Cuando se complete este proceso, haga que la directiva de lectura aparezca en el currículum del archivo MAKE.

3. anular instrucción

Si una variable ya está configurada como argumento de comando, se ignora en el archivo MAKE para tareas normales. Si desea establecer una variable de archivo MAKE incluso si está configurada como argumento de comando, puede usar una directiva de anulación, que es una línea que se ve así:

override variable = value

or

override variable := value

4,=、+=、:=、?=

= Asignación directa
:= Ignorar la asignación anterior
+= ¿Agregar
?= Si no hay una definición previa, la definición entrará en vigor

9. Vuelva a compilar el archivo Makefile

El programa make es una utilidad inteligente y funciona en función de cambios en los archivos fuente. Si hay cuatro archivos main.cpp, hello.cpp, factorial.cpp y funciones.h. Todos los archivos restantes aquí dependen de funciones.h, y main.cpp depende de hello.cpp y factorical.cpp. Entonces, si realiza algún cambio en funciones.h, todos los archivos fuente se volverán a compilar para generar nuevos archivos objeto. Pero si se realiza algún cambio en main.cpp, ya que esto no depende de ningún otro filtrado, en este caso solo se volverá a compilar el archivo main.cpp y no se volverá a compilar hellp.cpp factorial.cpp.

1. Condiciones para recompilar

Mientras compila un archivo, MAKE verifica el archivo de destino y compara las marcas de tiempo; si el archivo de origen tiene una marca de tiempo actualizada que es más reciente que el archivo de destino, entonces se generará un nuevo archivo de objeto, asumiendo que el archivo de origen ha sido modificado.

2. Evite recompilar

Es posible que el proyecto incluya miles de archivos. A veces es posible que haya cambiado un archivo fuente pero no desee volver a compilar todos los archivos que dependen de él. Por ejemplo, supongamos que agrega una macro a un archivo de encabezado o una declaración del que dependen muchos otros archivos. Se supone que cualquier cambio en los archivos de encabezado requerirá volver a compilar todos los archivos relacionados, pero tenga en cuenta que no es necesario volver a compilarlos y es mejor no perder el tiempo esperando a que se compilen.

  • Se pueden utilizar -tindicadores si se esperan cambios en los archivos de encabezado antes de que ocurran problemas. Este indicador le indica al comando make que no ejecute la regla, sino que marque el objetivo hasta el momento cambiando su última fecha de modificación. Sigue estos pasos:

    • 1. Utilice el comando 'make' para recompilar si realmente necesita recompilar los archivos fuente.
    • 2. Realice cambios en el archivo de encabezado.
    • 3. Utilice el comando -tpara registrar todos los archivos de destino como actualizados. La próxima vez que ejecute make, los cambios en los archivos de encabezado no provocarán ninguna recompilación.
  • Si se han modificado los archivos de encabezado, será necesario volver a compilar algunos archivos y será demasiado tarde para hacerlo. En su lugar, puede utilizar -oindicadores de archivo, que marcan un archivo específico como old. Esto significa que el archivo en sí no se reproducirá y nada más se reproducirán sus instrucciones. Sigue estos pasos:

    • 1. La recompilación de archivos fuente requiere la preparación de archivos de encabezado específicos independientes make -o headerfile. Si hay varios archivos de encabezado involucrados, use una -oopción separada para cada archivo de encabezado.
    • 2. Toque todos los archivos de destino make -tpara evitar volver a compilarlos.

3, toque

Toque actualiza la biblioteca a la última hora para evitar el problema de que los proyectos no se actualicen debido a intervalos de tiempo demasiado cortos.
Por ejemplo:

touch  xxx.cpp

10. Otras funciones de Makefile

1. Utilice make de forma recursiva

El uso recursivo significa usar make como comando en un archivo MAKE. Esta técnica es muy útil cuando desea que varios subsistemas de archivos MAKE compongan un sistema más grande. Por ejemplo, digamos que tiene un subdirectorio que tiene su propio archivo MAKE y desea ejecutar make en el archivo MAKE del subdirectorio. Esto puede hacerse de la siguiente manera:

#方式一:先切换目录再去make编译
subsystem:
        cd subdir && $(MAKE)

or, equivalently
#方式二:编译时去寻找切换目录 	
subsystem:
        $(MAKE) -C subdir

Es posible escribir copias recursivas de este ejemplo simplemente mediante el comando make, pero hay muchas cosas que entender sobre cómo y por qué funcionan, y cómo interviene el make de nivel subsuperior.

2. Variables de comunicación a subhacer

Los valores de las variables make de nivel superior se pueden pasar a subentornos, mediante solicitud explícita. Estas variables se definen en el submake como valores predeterminados, pero no anularán las especificadas en el submakefile a menos que se use el modificador `-e'.

Al transmitir o exportar una variable, la variable y su valor se agregan al entorno en el que se ejecuta cada comando. Submake A su vez, make utiliza valores de variables de entorno para inicializar sus tablas.

Las variables especiales SHELL y MAKEFLAGS siempre se exportan (a menos que se cancele la exportación). MAKEFILES exporta si lo configura en cualquier cosa.

Si desea exportar un subfabricante de una variable específica, utilice la directiva de exportación, como esta:

export variable ...

Si desea evitar que se exporte una variable, utilice la directiva deshacer exportación, como esta:

unexport variable ...

3. Variable MAKEFILES

MAKEFILES, macro predefinida de entorno, si se define una variable de entorno, haga una lista de nombres de archivos MAKE adicionales (separados por espacios) antes de que otros consideren que sus valores se pueden leer. Esto es muy parecido a la directiva de inclusión: busca estos archivos en diferentes directorios.
El objetivo principal de MAKEFILES es comunicarse entre llamadas recursivas MAKE sin informar errores, lo que complica fácilmente el proyecto.但没有必要,最好不用定义和使用该变量

LDFLAGS=-lstdc++
all:hello install
	@echo "MAKEFILES=$(MAKEFFILES)"

4. Los archivos de encabezado se incluyen en diferentes directorios.

Si colocó sus archivos de encabezado en un directorio diferente y ejecutó make en un directorio diferente, entonces debe indicar la ruta a los archivos de encabezado. Esto se puede hacer usando -Iopciones en el archivo MAKE. Suponiendo que el archivo funciones.h está disponible en /home/yidaoyun/header y otros archivos en /home/yidaoyun/src/, entonces los archivos se escribirán de la siguiente manera.

INCLUDES = -I "/home/yidaoyun/header"
CC = gcc
LIBS =  -lm
CFLAGS = -g -Wall
OBJ =  main.o factorial.o hello.o

hello: ${
    
    OBJ}
   ${
    
    CC} ${
    
    CFLAGS} ${
    
    INCLUDES} -o $@ ${
    
    OBJS} ${
    
    LIBS}
.o:.cpp
   ${
    
    CC} ${
    
    CFLAGS} ${
    
    INCLUDES} -c $<

5. Agregue más variables de texto

Normalmente, se utiliza para agregar más texto al valor de una variable ya definida.
La línea make contiene +=algo así:

objects += another.o

Esto toma el valor del objeto variable y agrega el texto another.o(precedido por un solo espacio). por lo tanto:

objects = main.o hello.o factorial.o
objects += another.o

establecer 文件main.o hello.o factorial.o another.oobjeto.
El uso +=es similar a:

objects = main.o hello.o factorial.o
objects := $(objects) another.o

6. Continuación de línea en Makefile

Si no le gustan las líneas demasiado largas en el Makefile, puede usar barras invertidas \, 但反斜杠后面不能有任何字符(空格,tab建,字母,下划线等)como se muestra a continuación.

OBJ =  main.o factorial.o \
	hello.o

is equivalent to

OBJ =  main.o factorial.o hello.o

7. Ejecute Makefile desde el símbolo del sistema.

Si ha preparado un Makefile con el nombre "Makefile", simplemente escriba en el símbolo del sistema y ejecutará el Makefile. Pero si hay algún otro nombre para el Makefile, utilice el siguiente comando

make -f your-makefile-name

11. Caso Makefile

Este es un ejemplo de cómo compilar el programa de saludo Makefile. Este programa contiene tres archivos main.cpp, factorial.cpp, hello.cpp.

# Define required macros here
SHELL = /bin/sh

OBJS =  main.o factorial.o hello.o
#CFLAG编译参数,-Wall:开启所有警告,-g:开启调试信息
CFLAG = -Wall -g
CC = gcc
#INCLUDES:依赖文件,没有就空,-I:当前文件
INCLUDES = -I .
#LIBS 依赖库
LIBS = -lstdc++

hello:${
    
    OBJS}
	${
    
    CC} ${
    
    CFLAGS} -o $@ $^ ${
    
    LIBS}

clean:
	-rm -f *.o hello

.o:.cpp
	${
    
    CC} ${
    
    CFLAGS} ${
    
    INCLUDES} -c $<
  • Para construir el programa hola utilice el proyecto hola "make". Si emite el comando "make clean", eliminará todos los objetos disponibles en el archivo MAKE en el directorio actual.

Resumir

1. Teclas de acceso directo en el modo de comando vim:
u: deshace todas las entradas antes del último guardado.
control+r: Restaura todas las entradas antes del último guardado.
Presione d dos veces: elimine una línea.

Supongo que te gusta

Origin blog.csdn.net/MOON_YZM/article/details/131098875
Recomendado
Clasificación