Навязать заказ на предпосылки цели
У меня есть фрагмент makefile:
all: $(objects)
fresh: clean all
clean: ;rm $(objects)
Здесь я хочу убедиться, что когда я делаю make fresh
- clean
должен предшествовать all
,
Но как я могу убедиться в этом, учитывая, что, когда я делаю make all
, clean
не должно быть сделано?
Я могу представить, что один из способов может быть таким
fresh: clean
make all
Это правильный (или единственный) способ решить эту проблему?
2 ответа
Если вы используете GNU make:
all:
@echo $@
@sleep 1
@echo end $@
clean:
@echo $@
@sleep 1
@echo end $@
fresh:: clean
fresh:: all
.PHONY: clean fresh all
Обратите внимание на двойное двоеточие после целиs fresh
! Смотрите документацию:
Правила двойного двоеточия для цели выполняются в том порядке, в котором они появляются в make-файле.
Если вы бежите make -j2 fresh
это показывает, что работает как ожидалось:
clean
end clean
all
end all
Но с fresh:: clean all
не работает должным образом параллельно (может быть, неожиданно).
С BSD делают:
all:
@echo $@
@sleep 1
@echo end $@
clean:
@echo $@
@sleep 1
@echo end $@
fresh: clean all
@echo $@
.ORDER: clean all
.PHONY: clean all fresh
Обратите внимание, что строка начинается с .ORDER
, Это хорошо работает и при распараллеливании (см. Man make). Без распараллеливания порядок зависимостей в строке fresh:
на счет.
Как вы уже предлагаете в своем вопросе, позвонив make
рекурсивно на том же make-файле для цели all
в рецепте, обязательным условием которого является clean
:
# At the very beginning of the makefile
CURRENT_MAKEFILE := $(lastword $(MAKEFILE_LIST))
# ...
.PHONY: fresh
fresh: clean
$(MAKE) -f $(CURRENT_MAKEFILE) all
Это накладывает порядок, так как цель fresh
зависит от предпосылки clean
, clean
рецепт будет выполнен раньше fresh
рецепт, который в свою очередь выполнит all
рецепт.
Обратите внимание, что я использую здесь $(MAKE)
вместоmake
для рекурсии.