'How can I get a Makefile target to be called multiple times?
In the simple example below, I want to do a make dist and have the distclean target executed before distdebug and distrelease.
.PHONY: distclean
dist: distdebug distrelease
@echo in dist
distdebug: distclean
@echo in distdebug
distrelease:
@echo in distrelease
distclean:
@echo in distclean
Unfortunately, despite using .PHONY, distclean is only called once:
vagrant@precise32:/tmp$ make dist
in distclean
in distdebug
in distrelease
in dist
I'm guessing that Make knows that its already run distclean once, so it's not running it again. How can I make it run distclean multiple times?
Solution 1:[1]
You can't using normal rules. Make will only ever build any given target exactly one time. You can do it using recursive make invocations:
distdebug:
$(MAKE) distclean
@echo in distdebug
distrelease:
$(MAKE) distclean
@echo in distrelease
In general it's a good idea to plan your build differently, though, and have targets for different types of builds put into different subdirectories. That way you don't HAVE to clean in between.
Solution 2:[2]
I was looking for something similar, i.e. performing the same pattern (%) target more than once. And I don't like recursive make invocations. Anyway, I ended up in this solution:
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
alternatively:
run: run-foo run-foo.2 run-bar run-foo.3
@true
build-%:
@echo "build-$*"
.SECONDEXPANSION:
run-%: build-$$(basename $$*)
@echo "run-$(basename $*)"
This makefile can run-anything up to three times by adding the extensions .2 and .3 to anything, but it will only build anything once. I hope you get the idea.
> make run
build-foo
run-foo
run-foo
run-foo
build-bar
run-bar
Solution 3:[3]
You don't need recursive make calls or enumerated rules. You can just using pattern matching to generate a different distclean alias for your debug and release steps:
.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
So you can make and get:
in distclean
in distdebug
in distclean
in distrelease
in dist
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | MadScientist |
| Solution 2 | |
| Solution 3 | mwag |
