如何让一个Makefile目标被多次调用?

6
在下面的简单示例中,我想要执行make dist并在distdebugdistrelease之前执行distclean目标。
.PHONY: distclean

dist: distdebug distrelease
    @echo in dist

distdebug: distclean
    @echo in distdebug

distrelease:          
    @echo in distrelease

distclean:
    @echo in distclean

很遗憾,尽管使用了.PHONY,但distclean仅会被调用一次:
vagrant@precise32:/tmp$ make dist
in distclean
in distdebug
in distrelease
in dist

我猜测Make已经知道它已经运行了distclean一次,因此不会再次运行。那么如何让它多次运行distclean呢?


你的问题帮助我做了相反的事情。在我的情况下,我想让 distclean 只被调用一次。 - Tyler Collier
3个回答

14

你不能使用普通规则。make 只会构建每个目标一次。你可以使用递归 make 调用来完成此操作:

distdebug:
        $(MAKE) distclean
        @echo in distdebug
distrelease:
        $(MAKE) distclean
        @echo in distrelease

通常情况下,最好采用不同的计划来构建,将不同类型的构建目标放入不同的子目录中。这样你就不必每次都要清理。


4

我在寻找类似的东西,即对相同模式(%)的目标执行多次。并且我不喜欢递归的make调用。无论如何,最终我采用了这个解决方案:

run-%: build-%
    @echo "run-$(basename $*)"

build-%:
    @echo "build-$*"

build-%.2: build-%; @true
build-%.3: build-%; @true

run: run-foo run-foo.2 run-foo.3 run-bar
    @true

另外一种选择:

run: run-foo run-foo.2 run-bar run-foo.3
    @true

build-%:
    @echo "build-$*"

.SECONDEXPANSION:

run-%: build-$$(basename $$*)
    @echo "run-$(basename $*)"

这个 makefile 可以通过在任何东西后面添加扩展名 .2 和 .3 来运行任何东西,但它只会构建一次任何东西。希望你明白这个想法。

> make run
build-foo
run-foo
run-foo
run-foo
build-bar
run-bar

通过使用.SECONDEXPANSION:,可以消除先决条件中的任何“扩展名”,上述makefile可以同时简化和概括,参见上面的替代方案。 - Christian Brolin

1

您无需使用递归make调用或枚举规则,只需使用模式匹配为调试和发布步骤生成不同的distclean别名:

.PHONY: dist%

dist: distdebug distrelease
    @echo in dist

distclean-%: # matches to distclean-debug, distclean-release etc 
    @echo in distclean

distdebug distrelease: dist% : distclean-% dist-% # clean first, then run

dist-debug:
    @echo in distdebug

dist-release:
    @echo in distrelease


所以你可以创建和获取:
in distclean
in distdebug
in distclean
in distrelease
in dist

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接