Несколько правил определяют один и тот же фальшиво-зависимый, зависимый выполняется только один раз - PullRequest
2 голосов
/ 02 августа 2009

У меня есть вопрос, касающийся примера сборочного файла GNU:

.PHONY: $(subdirs) build x y

subdirs =  a b c

build: x y

x: target=prepare
x: $(subdirs)

y: target=build
y: $(subdirs)

$(subdirs):
    $(make) -f $@/makefile $(target)

Когда я запускаю make, я ожидаю, что make будет вызываться для каждого подкаталога с указанием цели 'prepare', а затем цели 'build'. К сожалению, цель $ (subdirs) выполняется один раз (делая цель 'prepare'), но не выполняется снова для цели 'build'.

Похоже, что для правила x make определяет, что цель $ (subdirs) должна быть выполнена, но для правила y цель $ (subdirs) актуальна.

Есть ли способ это исправить?

Спасибо!

Ответы [ 2 ]

4 голосов
/ 02 августа 2009

Созданный вами make-файл предполагает, что команды для цели $(subdirs) будут выполняться два раза: один раз для x и второй раз для y. К сожалению, это не так, как работают make-файлы и зависимости. Команды для цели запускаются не более одного раза при каждом вызове make (за исключением необычных обстоятельств, таких как изменение make-файлов во время запуска make).

Следующее будет работать в системах UNIX-стиля. Он просто запускает подкаталог делает в цикле, один за другим:

subdirs = a b c

.PHONY: build
build:
    for dir in $(subdirs); do \
      $(MAKE) -f $$dir/makefile prepare; \
      $(MAKE) -f $$dir/makefile build; \
    done

Если вам нужно построить подкаталоги параллельно, вы можете использовать следующее:

subdirs = a b c

.PHONY: build
build: $(addprefix build-,$(subdirs))

define submake-rule
  .PHONY: build-$(1)
  build-$(1):
    $(MAKE) -f $(1)/makefile prepare
    $(MAKE) -f $(1)/makefile build
endef

$(foreach dir,$(subdirs),$(eval $(call submake-rule,$(dir))))

Это определяет правило build-<dirname> для каждого элемента в $(subdirs) и делает цель build зависимой от всех из них. В качестве дополнительного бонуса, это также переносимо на Windows, не требуя использования оболочки Cygwin bash или аналогичной. Недостатком является то, что это немного сложнее понять.

1 голос
/ 02 августа 2009

Я предпочитаю метод Ville, чем вашу попытку.
Как правило, есть два способа получить многократный прогон с разными аргументами.

  1. Напишите внешний скрипт (или, как идея Ville повторяется во внешнем Makefile)
    • Напишите all правило в каждом подфайл-файле для запуска prepare с последующим build
    • это объединит комбинацию prepare+build в подфайлы Makefile и,
      вы просто запустите all из внешнего файла Makefile - гораздо более модульный.

Это один пример, где вы можете легко приземлиться с излишне сложным Makefile

...