2

我对下面的 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时,我希望为每个指定目标'prepare'然后是目标'build'的子目录调用make。不幸的是,$(subdirs) 目标执行一次(使“准备”目标),但不会再次为“构建”目标执行。

似乎对于规则 x,make 确定需要运行 $(subdirs) 目标,但对于规则 y,$(subdirs) 目标是最新的。

有没有什么办法解决这一问题?

谢谢!

4

2 回答 2

4

您发布的 makefile 似乎假设$(subdirs)目标的命令将运行两次:一次 for x,第二次 for y. 不幸的是,这不是 makefile 和依赖项的工作方式。目标的命令在每次 make 调用时最多运行一次(除非出现异常情况,例如在 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 或类似的。缺点是它有点难以理解。

于 2009-08-02T17:11:44.870 回答
1

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

  1. 编写一个外部脚本(或者,就像Ville在外部 Makefile 中迭代的想法)
    • all在每个要运行的子 Makefile 中编写一个规则,prepare然后build
    • 这会将prepare+build组合集成到子 Makefile 中,并且
      您只需all从外部 Makefile 运行一个 - 更加模块化。

这是一个示例,您可以轻松地完成不必要的复杂操作Makefile

于 2009-08-02T17:26:39.063 回答