问题
I have a makefile snippet:
all: $(objects)
fresh: clean all
clean: ;rm $(objects)
Here, I want to ensure that when I do make fresh
- clean
should precede all
.
But how can I make sure this, given that when I do make all
, clean
should not be made?
I can imagine that one way could be like this
fresh: clean
make all
Is it the right (or the only) way to solve this issue?
回答1:
If you use GNU make:
all:
@echo $@
@sleep 1
@echo end $@
clean:
@echo $@
@sleep 1
@echo end $@
fresh:: clean
fresh:: all
.PHONY: clean fresh all
Please note the double colon after targets fresh
! See the documentation:
The double-colon rules for a target are executed in the order they appear in the makefile.
If you run make -j2 fresh
it shows it works as expect:
clean
end clean
all
end all
But with fresh:: clean all
doesn't work properly parallel (maybe unexpected).
With BSD make:
all:
@echo $@
@sleep 1
@echo end $@
clean:
@echo $@
@sleep 1
@echo end $@
fresh: clean all
@echo $@
.ORDER: clean all
.PHONY: clean all fresh
Note the line begin with .ORDER
. It works well in parallelization too (see man make). Without parallelization the order of dependencies in line fresh:
counts.
回答2:
As you already suggest in your question, calling make
recursively on the same makefile for the target all
in a recipe whose prerequisite is clean
:
# At the very beginning of the makefile
CURRENT_MAKEFILE := $(lastword $(MAKEFILE_LIST))
# ...
.PHONY: fresh
fresh: clean
$(MAKE) -f $(CURRENT_MAKEFILE) all
This imposes an order, since the target fresh
depends on the prerequisite clean
, clean
's recipe will be executed before fresh
's recipe, which in turn will execute all
's recipe.
Note that I'm using here $(MAKE) instead of make for the recursion.
来源:https://stackoverflow.com/questions/52036534/impose-an-order-for-the-prerequisites-of-a-target