我对下面的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)目标是最新的。
有什么方法可以解决这个问题吗?
谢谢!
答案 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
的方法而不是你的尝试
通常有两种方法可以使用不同的参数进行多次运行。
Ville
的想法迭代在外部Makefile中)
all
规则以运行prepare
,然后build
prepare+build
组合,并且
你只是从外部Makefile运行all
- 更加模块化。这是一个例子,您可以轻松地使用不必要的复杂Makefile