Ответ 1
SUBDIRS = a b c
default: all
$(SUBDIRS)::
$(MAKE) -C [email protected] $(MAKECMDGOALS)
all clean : $(SUBDIRS)
Я ищу элегантный способ распараллеливания заданий в GNU make. Вот пример того, что я сделал до сих пор. Создавайте процессы каталогов dir-1, dir-2 и dir-3 серийным образом, что логично, но не мое намерение:
SUBDIRS=dir-1 dir-2 dir-3
default: all
all:
@for dir in $(SUBDIRS); do (cd $$dir; $(MAKE)); done
.PHONY: clean
clean:
@for dir in $(SUBDIRS); do (cd $$dir; $(MAKE) clean); done
Есть ли способ поддержать параллельную обработку этих каталогов с помощью опции -j, не указав конкретные цели для каждого каталога?
SUBDIRS = a b c
default: all
$(SUBDIRS)::
$(MAKE) -C [email protected] $(MAKECMDGOALS)
all clean : $(SUBDIRS)
Это, вероятно, не будет отвечать на ваш вопрос напрямую, но помимо того, что предлагают другие ответы, я бы рекомендовал изучить нерекурсивные методы создания. Это поистине элегантный способ распараллеливать сборку, хотя, в зависимости от существующих Make файлов, может потребоваться значительное усилие. Нерекурсивный make имеет преимущества, которые не ограничиваются простой параллелизацией: он видит полный график зависимостей, поэтому ему не нужно создавать слишком мало или слишком много, что означает более быстрое (иногда намного более быстрое) время сборки.
Некоторые ресурсы:
Я обнаружил, что при использовании правила:: (двойное двоеточие) я не мог найти способ принудительного упорядочения, если бы были какие-то зависимости между app
, lib
и doc
. После прочтения большей части руководства GNU Make, я применил следующие правила для обеспечения соответствия зависимостей одновременно с созданием рекурсивного make. Обратите внимание, что существует правило .PHONY, чтобы заставить make войти в каталог, даже если каталог уже существует.
SUBDIRS = app lib doc
default: all
app: lib
.PHONY: $(SUBDIRS)
$(SUBDIRS):
$(MAKE) -C [email protected] $(MAKECMDGOALS)
all clean install: $(SUBDIRS)
Являются ли dir-1, dir-2 и dir-3 взаимозависимыми или независимыми?
У меня похожая структура, но зависимость между подкаталогами, поэтому я предпочел просто использовать параллельные сборки в каждом из подкаталогов. Вы получите это через
## default to four parallel runs
MAKEFLAGS += -j 4
all:
@for dir in $(SUBDIRS); do (cd $$dir; $(MAKE) ); done
Но еще один трюк - прочитать SUBDIRS
в руководстве по установке - вам не нужен цикл for
, поскольку make
может развернуть это для вас. Попробуйте что-то вроде
## default to four parallel runs
MAKEFLAGS += -j 4
SUBDIRS = dir-1 dir-2 dir-3
$(SUBDIRS): #whatever your depends here
$(MAKE) -C [email protected]