0
votes

I have a makefile which can compile a release build or a debugging build (i.e. with -O3 or -g respectively. The first and default one is release so make is equivalent to make release. Sometimes I make debug but am so used to just typing make that the next time I compile it goes back to release.

Is there a way the makefile could remember the last target specified and default to that if no arguments are given?

This has a similar title, but is really a different question: How does "make" app know default target to build if no target is specified?

2

2 Answers

1
votes

I like this a bit better:

LAST_TARGET_FILE=.last_target
UPDATE_LAST_TARGET=@echo "LAST_TARGET=$@" >$(LAST_TARGET_FILE)

-include $(LAST_TARGET_FILE)

.PHONY: default
default: $(firstword $(LAST_TARGET) release)

.PHONY: debug
debug:
    $(UPDATE_LAST_TARGET)
    echo debug

.PHONY: release
release:
    $(UPDATE_LAST_TARGET)
    echo release
1
votes

This writes the last target name into a file, .default_make_target, which is then used as the default target when no arguments are given. It shows the correct target name in the output and exits with Nothing to be done for 'target'. correctly when its out of date.

DEFAULT_TARGET=debug
LAST_TARGET_FILE=.default_make_target
LAST_TARGET=$(foreach f, $(wildcard $(LAST_TARGET_FILE)), $(shell cat $(f)))

.PHONY: debug release clean

.DEFAULT_GOAL:= $(or $(LAST_TARGET),$(DEFAULT_TARGET))

debug: CFLAG_OPTS+= -g
debug: CHOSEN_TARGET=debug
debug: real_target

release: CFLAG_OPTS+= -O3
release: CHOSEN_TARGET=release
release: real_target

real_target:
    @echo $(CHOSEN_TARGET) > $(LAST_TARGET_FILE)
    echo '$(CFLAG_OPTS)' > real_target #just an example

clean:
    rm -f real_target

Testing...

> make debug
echo '-g' > real_target
> make
make: Nothing to be done for 'debug'.
> make clean
rm -f real_target
> make release
echo '-O3' > real_target
> make
make: Nothing to be done for 'release'.
>

*UPDATED:

  • Previously I had @echo debug > $(LAST_TARGET_FILE) as the body of the phony debug rule (and likewise for release), which meant debug/release were always out of date. Instead, it needs to be run in the body of a real target, for which CHOSEN_TARGET is set.

  • Rather than default: $(if...), using .DEFAULT_GOAL:= now causes the correct target to be printed when up to date. For example make: Nothing to be done for 'release'.