Зацикливание - это вообще то, чего вы хотите избежать. Вместо этого, объявляйте серию целей для каждого репо.
repos := ws-led tools-extension javt-ra
.PHONY: all clone
all: $(patsubst %,%/.built,$(repos))
clone: $(patsubst %,%/.git,$(repos))
%/.built: %/.git
cd $*; docker build -t $* .
touch $@
%/.git:
git clone https://github.company.corp/dev-wi/$*.git
Файл флага .built
является чем-то вроде бородавки и может быть с пользой заменен чем-то более полезным, например, выводом из docker build
.
all: $(patsubst %,%/docker-build.log,$(repos))
%/docker-build.log: %/.git
cd $*; docker build -t $* . >&2 | tee docker-build.log
Причина, по которой мы обычно стараемся избегать циклов, состоит в том, чтобы позволить make
правильно выполнять свою основную работу - избегать повторного запуска команд, когда цель уже обновлена. Так, например, если вы изменили только ws-led
, вы не хотите принудительно перестраивать две другие.
Сказав это, $(patsubst ...)
- это всего лишь oop своего рода. ; он в основном зацикливается на repos
и создает небольшой фрагмент текста вокруг каждого. Без patsubst
мы могли бы написать
all: ws-led/.built tools-extension/.built javt-ra/.built
, в котором просто говорится, что для создания all
нам нужно сделать эти три; а затем
%/.built: %/.git
говорит, что для всего, что соответствует шаблону, оно зависит от того же стебля с /.git
после него. Таким образом, в другом пустом каталоге make
обнаружит, что
- для создания
all
, нам нужно сделать ws-led/.built
, tools-extension/.built
и javt-ra/.built
;
В будущем, когда make
обнаружит, что ws-led
новее ws-led/.built
, он построит его снова; но если это не так, он придет к выводу, что никакой работы не требуется, и т. д. c для других целей. Так мы избегаем ненужного строительства. но очевидно, что Makefile
должным образом содержит формализацию каждой соответствующей зависимости. (В этом случае, в идеале, вы бы хотели, чтобы был способ узнать, когда вышестоящий поток Git изменился и что-то должно быть извлечено локальным Makefile
; в настоящее время все просто считается выполненным, если локальный Git клон не получил никаких обновлений.)