2010-07-10 27 views
241
CC=g++ 
CFLAGS=-c -Wall 
LDFLAGS= 
SOURCES=main.cpp hello.cpp factorial.cpp 
OBJECTS=$(SOURCES:.cpp=.o) 
EXECUTABLE=hello 

all: $(SOURCES) $(EXECUTABLE) 

$(EXECUTABLE): $(OBJECTS) 
    $(CC) $(LDFLAGS) $(OBJECTS) -o [email protected] 

.cpp.o: 
    $(CC) $(CFLAGS) $< -o [email protected] 

¿Qué hacen exactamente el [email protected] y $<?

+4

El enlace de arriba se ha roto, aquí está la otra: http://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html – asciz

+1

Hola lo que hace este" .cpp.o : "como un objetivo? (¿la última línea?). –

+3

El ".cpp.o:" significa construir ".o" (archivos de objetos) desde ".cpp" (archivos fuente) – jaguzu

Respuesta

287

[email protected] es el nombre del archivo que se está generando, y $< el primer requisito previo (normalmente el archivo de origen). Puede encontrar una lista de todas estas variables especiales en el GNU Make manual.

Por ejemplo, considere la siguiente declaración:

all: library.cpp main.cpp 

En este caso:

  • [email protected] evalúa a all
  • $< evalúa a library.cpp
  • $^ evalúa a library.cpp main.cpp
+5

Vale la pena señalar que '$ @' no necesariamente tiene que terminar siendo un archivo, sino que también podría ser el nombre de un objetivo '.PHONY'. – Ephemera

+0

¿Puedo agregar a las opciones de la línea de comandos esto: '$ @ s' para generar ensamblaje-salida como name.os? –

57

Las [email protected] y $< se llaman variables automáticas. El [email protected] es la variable de salida. $< es la primera variable de entrada. Por ejemplo:

hello.o: hello.c hello.h 
     gcc -c $< -o [email protected] 

Aquí, hello.o es el archivo de salida. Esto es a lo que se expande [email protected]. La primera dependencia es hello.c. Eso es a lo que se expande $<.

La bandera -c genera el archivo .o; ver man gcc para una explicación más detallada. El -o especifica el archivo a la salida.

Para obtener más información, puede leer this.

Además, puede consultar los manuales de GNU. Hay una manera de depurar su archivo MAKE para entenderlo mejor.

Esta es la salida de la base de datos makefile:

$make -p 
+1

Su respuesta suena como '$ <' se ampliará a 'hello.c hello.h' (ambos). Por favor, aclarar –

+0

Sí, incluirá tanto hello.c como hello.h –

+8

'$ <' es solo el primer elemento. Para incluir todo, use '$ ^'. –

23

De Managing Projects with GNU Make, 3rd Edition (que está bajo términos de la Public): Las variables

automáticas son fijados por make después de una regla se corresponde . Ellos proporcionan acceso a los elementos de las listas de objetivos y requisitos previos para que no tenga que especificar explícitamente ningún nombre de archivo.Son muy útiles para evitar la duplicación de código, pero son críticos al definir reglas de patrón más generales.

hay siete “núcleo” variables automáticas:

  • [email protected]: El nombre del archivo que representa el objetivo.

  • $%: El elemento de nombre de archivo de una especificación de miembro de archivo.

  • $<: El nombre de archivo del primer requisito previo.

  • $?: los nombres de todos los requisitos previos que son más nuevos que el objetivo, separados por espacios.

  • $^: nombres de archivo de todos los requisitos previos, separados por espacios. Esta lista tiene nombres de archivos duplicados eliminados, ya que para la mayoría de los usos, como compilar, copiar, etc., no se desean duplicados.

  • $+: Similar a $^, esto es los nombres de todos los requisitos previos separados por espacios, excepto que $+ incluye duplicados. Esta variable fue creada para situaciones específicas, como argumentos para vinculadores, donde los valores duplicados tienen un significado.

  • $*: La raíz del nombre de archivo de destino. Una raíz suele ser un nombre de archivo sin su sufijo. Su uso fuera de las reglas de patrón es desaconsejado.

Además, cada una de las variables anteriores tiene dos variantes para compatibilidad con otras marcas. Una variante devuelve solo la parte del valor del directorio . Esto se indica al agregar una "D" al símbolo , $(@D), $(<D), etc. La otra variante solo devuelve el archivo parte del valor. Esto se indica al agregar una "F" al símbolo , $(@F), $(<F), etc. Tenga en cuenta que estos nombres de variantes son más de de un carácter de largo, por lo que deben estar entre paréntesis. GNU make proporciona una alternativa más legible con las funciones dir y notdir .

9

El Makefile construye el ejecutable hello si cualquiera de main.cpp, hello.cpp, factorial.cpp cambiado.El Makefile más pequeña posible para lograr esa especificación podría haber sido:

hello: main.cpp hello.cpp factorial.cpp 
    g++ -o hello main.cpp hello.cpp factorial.cpp 
  • Pro: muy fácil de leer
  • con: pesadilla para el mantenimiento, la duplicación de las dependencias del C++
  • con: problema de eficiencia, recompilamos todo C++ aunque haya cambiado uno solo

Para mejorar lo anterior, solo compilamos los archivos C++ que se editaron. Luego, solo vinculamos los archivos de objetos resultantes.

OBJECTS=main.o hello.o factorial.o 

hello: $(OBJECTS) 
    g++ -o hello $(OBJECTS) 

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

hello.o: hello.cpp 
    g++ -c hello.cpp 

factorial.o: factorial.cpp 
    g++ -c factorial.cpp 
  • pro: correcciones de emisión de la eficiencia
  • con: nueva pesadilla de mantenimiento, el potencial de error tipográfico en las reglas archivos de objetos

Para mejorar esto, podemos reemplazar todas las reglas de archivos objeto con una sola .cpp.o regla:

OBJECTS=main.o hello.o factorial.o 

hello: $(OBJECTS) 
    g++ -o hello $(OBJECTS) 

.cpp.o: 
    g++ -c $< -o [email protected] 
  • Pro: volver a tener un corto makefile, algo fácil de leer

Aquí la regla .cpp.o define cómo construir anyfile.o de anyfile.cpp.

  • $< partidos a primera dependencia, en este caso, anyfile.cpp
  • [email protected] coincide con el objetivo, en este caso, anyfile.o.

Los otros cambios presentes en el Makefile son:

  • Por lo que es más fácil de cambios compiladores de g ++ a cualquier compilador C++.
  • Haciendo que sea más fácil cambiar las opciones del compilador.
  • Haciendo que sea más fácil cambiar las opciones del enlazador.
  • Haciendo que sea más fácil cambiar los archivos fuente C++ y la salida.
  • Se agregó una regla predeterminada 'todo' que actúa como una comprobación rápida para garantizar que todos sus archivos fuente estén presentes antes de que se intente crear su aplicación.
Cuestiones relacionadas