Навязать заказ на предпосылки цели

У меня есть фрагмент 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 для рекурсии.

Другие вопросы по тегам