2010-04-26 3 views
44

Existe-t-il un moyen de réaffecter la valeur de la variable Makefile à l'intérieur du corps cible?Modifier la valeur de la variable Makefile à l'intérieur du corps cible

Ce que je suis en train de faire est d'ajouter des drapeaux supplémentaires pour la compilation de débogage:

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

test: clean debug_compile_flag compile compile_test 

debug_compile: 
    $(ERLCFLAGS) += -DTEST 

Donc, si j'invoque essai cible Je voudrais nettoyer mon environnement, ajouter quelques nouveaux drapeaux (comme -DTEST), recompilez le code entier (premières sources, puis modules de test).

Je ne veux pas copier/coller le code pour compiler avec de nouveaux drapeaux, car il y a beaucoup de logique ici et là.

Existe-t-il un moyen simple de redéfinir la valeur de la variable pour que je puisse réutiliser le code existant?

+0

double possible [Définir faire variable à la règle du temps d'exécution] (http://stackoverflow.com/questions/1909188/définir-make-variable à-règle-exécution-temps) –

Répondre

-5

Modifier: Comme expliqué par bêta dans le other answer, il est possible.


Non. Il n'y a aucun moyen de le faire dans le Makefile. Vous pouvez toutefois modifier la valeur d'une variable sur la ligne de commande make. Si vous réécrivez votre Makefile comme suit:

ERLCFLAGS += $(ERLCFLAGSADDED) 

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

test: clean compile compile_test 

Ensuite, vous pouvez invoquez faire pour effectuer vos tests en utilisant:

make ERLCFLAGSADDED=-DTEST test 
+0

Oui, je l'ai résolu le problème comme vous le suggérez, en cours d'exécution submake dans le debug_compile: ERLC_FLAGS = $ (ERLC_DEBUG_FLAGS) $ (MAKE) compilation Merci ! – paulgray

+0

Oh oui, très bien. Je n'ai pas pensé à cette invocation de submake. –

+0

L'invocation de submake est toujours utile si vous souhaitez exécuter une cible plusieurs fois avec différentes valeurs des indicateurs. Voir les documents que j'ai cités dans le commentaire ci-dessous. – ntc2

58

Oui, il existe un moyen facile de le faire, et sans réexécuter Make. Utilisez un target-specific variable value:

test: clean debug_compile 

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

L'ordre d'exécution est-il garanti ici? Ou pourrait-on faire -j2 foirer les choses? – Marenz

+2

[Docs] (http://www.gnu.org/software/make/manual/make.html # Target_002dspecific): "Sachez qu'un prérequis donné ne sera créé qu'une seule fois par invocation de make.Si le même fichier est un prérequis pour plusieurs cibles, et que chacune de ces cibles a une valeur différente pour la même cible- variable spécifique, la première cible à construire entraînera la construction de cette condition préalable et la condition préalable héritera de la valeur spécifique à la cible de la première cible, et ignorera les valeurs spécifiques à la cible de toutes les autres cibles. – ntc2

38

Une autre réponse est ici: Define make variable at rule execution time.

Pour les paresseux, vous pouvez avoir des règles telles que les suivantes (FLAG et DEBUG sont mes variables):

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

Seule version qui a fonctionné pour moi, merci! – Raphael

+1

J'ai beaucoup de problèmes avec '$ (eval xxx)', avec des tonnes d'effets secondaires étranges. Cela ne semble pas fonctionner aussi bien qu'une affectation de variable Makefile "réelle". – Cyan

+0

J'ai eu un problème avec la fonction 'eval' - J'ai des valeurs vides pour mes variables car la variable définie avec eval obtient sa valeur au début de l'exécution de la cible, pas quand cette ligne est atteinte. Par exemple, si vous créez des fichiers au début de la cible, et plus tard essayez de remplir une variable en utilisant 'eval FILES = $ (shell ls)', vos fichiers var seront vides –

0

Je voulais ajouter une cible dans un makefile pour exécuter des tests, ce qui impliquait recompiler le code source avec quelques drapeaux de débogage. La réponse de Ian: https://stackoverflow.com/a/15561911/ était la seule solution qui a fonctionné.

Voici le Makefile je suis venu avec, ce qui garantit l'ordre d'exécution lors de l'exécution 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) 
Questions connexes