Is there a way to reassign Makefile variable value inside of the target body?
What I am trying to do is to add some extra flags for debug compilation:
Edit: As explained by Beta in the other answer, it is possible.
No. There is no way to do this in the Makefile. You can however change the value of a variable on the make
command line. If you rewrite your Makefile as follows:
ERLCFLAGS += $(ERLCFLAGSADDED)
%.erl: %.beam
$(ERLC) $(ERLCFLAGS) -o ebin $<
test: clean compile compile_test
Then, you can invoke make to perform your tests using:
make ERLCFLAGSADDED=-DTEST test
Here is the solution I use:
PASSWORD = abc123
main: sub
@echo "in main" $(PASSWORD)
sub:
@echo "in sub" $(PASSWORD)
$(eval PASSWORD=qwerty)
@echo "in sub" $(PASSWORD)
If you run make main
then the output is:
in sub abc123
in sub qwerty
in main qwerty
You can see that the original value "abc123"
is overwritten in the sub
and the new value "qwerty"
is visible at the main
level.
Yes, there is an easy way to do it, and without rerunning Make. Use a target-specific variable value:
test: clean debug_compile
debug_compile: ERLCFLAGS += -DTEST
debug_compile: compile compile_test;
Another answer is here: Define make variable at rule execution time.
For the lazy, you can have rules like the following (FLAG
and DEBUG
are my variables):
.DBG:
$(eval FLAG += $(DEBUG))
To override on the command line try something like:
make prefix=<path to new dir> install
This won't change Makefile, but will alter the variable.
I wanted to add a target in a makefile to run tests, which implied recompiling the source code with some debug flags. Ian's answer: https://stackoverflow.com/a/15561911/ was the only solution that worked.
Here's the Makefile I came up with, which guaranties the order of execution when running 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 $@
@echo -e "Linking complete!\n"
$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.cc $(INCLUDES)
@mkdir -p $(OBJDIR) $(BINDIR)
$(CC) $(CFLAGS) -c $< -o $@
@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)