2010-04-26 9 views
44

¿Hay alguna manera de reasignar el valor de la variable Makefile dentro del cuerpo de destino?Cambiar el valor de la variable Makefile dentro del cuerpo de destino

Lo que estoy tratando de hacer es añadir algunas banderas adicionales para la compilación de depuración:

%.erl: %.beam 
    $(ERLC) $(ERLFLAGS) -o ebin $< 

test: clean debug_compile_flag compile compile_test 

debug_compile: 
    $(ERLCFLAGS) += -DTEST 

Así que si invoco prueba objetivo me gustaría limpiar mi entorno, añadir algunas nuevas banderas (como -DESTAR a los existentes), compilar todo el código una vez más (primeras fuentes, luego módulos de prueba).

No quiero copiar/pegar el código para compilar con algunos nuevos indicadores establecidos ya que hay mucha lógica puesta aquí y allá.

¿Hay alguna manera fácil de redefinir el valor de la variable para poder reutilizar el código existente?

+0

posible duplicado de [Definir hacer variable en tiempo de ejecución de la regla] (http://stackoverflow.com/questions/1909188/define-hacer-variable-en-reglas de ejecución en tiempo) –

Respuesta

-5

Editar: Según lo explicado por Beta en el other answer, es posible.


No. No hay forma de hacerlo en el Makefile. Sin embargo, puede cambiar el valor de una variable en la línea de comando make. Si se vuelve a escribir su Makefile de la siguiente manera:

ERLCFLAGS += $(ERLCFLAGSADDED) 

%.erl: %.beam 
    $(ERLC) $(ERLCFLAGS) -o ebin $< 

test: clean compile compile_test 

A continuación, puede invocar a make para llevar a cabo sus pruebas usando:

make ERLCFLAGSADDED=-DTEST test 
+0

Sí, he resuelto el problema como usted sugiere, corriendo submake en el debug_compile: ERLC_FLAGS = $ (ERLC_DEBUG_FLAGS) $ (MAKE) compilar Gracias ! – paulgray

+0

Oh sí, genial. No pensé en esta invocación de submake. –

+0

La invocación de submake sigue siendo útil si desea ejecutar un destino varias veces con diferentes valores de los indicadores. Ver los documentos que cité en el comentario a continuación. – ntc2

58

sí, hay una manera fácil de hacerlo, y sin volver a ejecutar Make. Utilice un target-specific variable value:

test: clean debug_compile 

debug_compile: ERLCFLAGS += -DTEST 
debug_compile: compile compile_test; 
+2

¿El orden de ejecución está garantizado aquí? ¿O podría hacer que -j2 arruine las cosas? – Marenz

+2

[Docs] (http://www.gnu.org/software/make/manual/make.html # Target_002dspecific): "Tenga en cuenta que un prerrequisito dado solo se generará una vez por invocación de make, a lo sumo. Si el mismo archivo es un requisito previo de objetivos múltiples, y cada uno de esos objetivos tiene un valor diferente para el mismo objetivo. variable específica, entonces el primer objetivo que se generará hará que se cree ese requisito previo y el requisito previo heredará el valor específico del objetivo del primer objetivo. Ignorará los valores específicos del objetivo de cualquier otro objetivo ". – ntc2

38

Otra respuesta está aquí: Define make variable at rule execution time.

Para los perezosos, puede tener reglas como las siguientes (FLAG y DEBUG son mi variables):

.DBG: 
    $(eval FLAG += $(DEBUG)) 
+2

única versión que funcionó para mí, gracias! – Raphael

+1

Tengo un montón de problemas con '$ (eval xxx)', con toneladas de extraños efectos secundarios. No parece funcionar tan bien como una asignación de variable Makefile "real". – Cyan

+0

Tuve un problema con la función 'eval' - Obtuve valores vacíos para mis variables porque la variable definida con eval obtiene su valor al principio de la ejecución del objetivo, no cuando se alcanza esta línea. Por ejemplo, si está creando algunos archivos al principio del objetivo y luego intenta llenar alguna variable usando 'eval FILES = $ (shell ls)', su var ARCHIVOS estará vacía –

0

que quería añadir un objetivo en un makefile para ejecutar las pruebas, lo que implicó volver a compilar el código fuente con algunos indicadores de depuración. La respuesta de Ian: https://stackoverflow.com/a/15561911/ fue la única solución que funcionó.

Aquí está el Makefile que se me ocurrió, lo que garantiza el orden de ejecución cuando se ejecuta make tests:

TARGET  = a.out 

CC   = g++ 
GENERIC_F = -Wall -Wextra -I. -Idoctest/doctest/ 

CFLAGS  = -O0 -std=c++11 $(GENERIC_F) 
DEBUG_MODE = -DDEBUG 

LINKER  = g++ 
LFLAGS  = $(GENERIC_F) -lm 

SRCDIR  = src 
OBJDIR  = build 
BINDIR  = bin 

SOURCES = $(wildcard $(SRCDIR)/*.cc) 
INCLUDES = $(wildcard $(SRCDIR)/*.h) 
OBJECTS = $(SOURCES:$(SRCDIR)/%.cc=$(OBJDIR)/%.o) 
rm   = rm -f 

.PHONY: clear_screen tests extend_cflags 

$(BINDIR)/$(TARGET): $(OBJECTS) $(INCLUDES) 
    $(LINKER) $(OBJECTS) $(LFLAGS) -o [email protected] 
    @echo -e "Linking complete!\n" 

$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.cc $(INCLUDES) 
    @mkdir -p $(OBJDIR) $(BINDIR) 
    $(CC) $(CFLAGS) -c $< -o [email protected] 
    @echo -e "Compiled "$<" successfully!\n" 

.PHONY: clean 
clean: 
    @$(rm) $(OBJECTS) 
    @echo "Cleanup complete!" 

.PHONY: remove 
remove: clean 
    @$(rm) $(BINDIR)/$(TARGET) 
    @echo "Executable removed!" 

clear_screen: 
    @clear 

extend_cflags: 
    $(eval CFLAGS += $(DEBUG_MODE)) 

tests: | remove extend_cflags $(BINDIR)/$(TARGET) clear_screen 
    @$(BINDIR)/$(TARGET) 
Cuestiones relacionadas