多个规则指定相同的假依赖,依赖只执行一次

时间:2009-08-02 13:48:22

标签: build-process makefile gnu-make

我对下面的GNU makefile示例有疑问:

.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 个答案:

答案 0 :(得分:4)

您发布的makefile似乎假设$(subdirs)目标的命令会运行两次:x一次,y第二次。不幸的是,这不是makefile和依赖项的工作方式。每次调用时,目标命令最多运行一次(除非发生异常情况,例如在make运行期间修改makefile)。

以下内容适用于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 shell或类似的。缺点是它有点难以理解。

答案 1 :(得分:1)

我更喜欢Ville的方法而不是你的尝试 通常有两种方法可以使用不同的参数进行多次运行。

  1. 写一个外部脚本(或者像Ville的想法迭代在外部Makefile中)
    • 在每个子Makefile中编写all规则以运行prepare,然后build
    • 这将在子Makefile中整合prepare+build组合,并且 你只是从外部Makefile运行all - 更加模块化。
  2. 这是一个例子,您可以轻松地使用不必要的复杂Makefile