gdw2
gdw2

Reputation: 8016

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?

Upvotes: 6

Views: 5694

Answers (3)

mwag
mwag

Reputation: 4035

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

Upvotes: 1

Christian Brolin
Christian Brolin

Reputation: 111

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

Upvotes: 4

MadScientist
MadScientist

Reputation: 100806

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.

Upvotes: 14

Related Questions