Callum M
Callum M

Reputation: 2080

Makefile: how do I get the same behaiour as $@ when using a variable directly?

I'm using similar code to https://stackoverflow.com/a/17845120/1375972 which includes:

TOPTARGETS := zip test clean

SUBDIRS := $(wildcard */.)

$(TOPTARGETS): $(SUBDIRS)
$(SUBDIRS):
    $(MAKE) -C $@ $(MAKECMDGOALS)

This runs whichever make command is passed (from TOPTARGETS) on every subdirectory, which is what I want.

However I want to have a target deploy which has this same behaviour only when an environment variable is set. Here's what I've tried:

deploy:
ifdef GITLAB_CI
    @echo "GITLAB_CI variable is defined, running deploy on all subdirectories"
    $(MAKE) -C $(SUBDIRS) $(MAKECMDGOALS)

else
    @echo "snip"
endif

Notice the $(MAKE) line is the same as the $(SUBDIRS) one, just with the $@ replaced with $(SUBDIRS) directly.

So the logic is when it runs in my CI it'll run the deploy recursively on all subdirectories, but when it's run locally it doesn't. The problem is that the $(SUBDIRS) in deploy doesn't behave as expected. When I run make deploy in a directory with 2 subdirectories:

> make deploy
GITLAB_CI variable is defined, running deploy on all subdirectories
/Library/Developer/CommandLineTools/usr/bin/make -C subdir1/. subdir2/. deploy
make[1]: *** No rule to make target `subdir2/.'.  Stop.
make: *** [deploy] Error 2

Compared to make clean (one of my TOPTARGETS):

> make clean
/Library/Developer/CommandLineTools/usr/bin/make -C subdir1/. clean
/Library/Developer/CommandLineTools/usr/bin/make -C subdir2/. clean

So when the TOPTARGETS are used, the $@ seems to unroll $(SUBDIRS) in a different way to when I write the same line myself with $@ substituted to $(SUBDIRS). Is there any way to get that behaviour myself in the deploy line? Or do I need to write my own for loop over $(SUBDIRS) inside that target?

Upvotes: 0

Views: 82

Answers (1)

Renaud Pacalet
Renaud Pacalet

Reputation: 29220

You could keep what works and add a minimal deploy rule:

TOPTARGETS := zip test clean

SUBDIRS := $(wildcard */.)

$(TOPTARGETS): $(SUBDIRS)
$(SUBDIRS):
    $(MAKE) -C $@ $(MAKECMDGOALS)

ifdef GITLAB_CI
deploy: $(SUBDIRS)
else
deploy:
    @echo "snip"
endif

Or, maybe even simpler:

TOPTARGETS := zip test clean
ifdef GITLAB_CI
TOPTARGETS += deploy
else
deploy:
    @echo "snip"
endif

SUBDIRS := $(wildcard */.)

$(TOPTARGETS): $(SUBDIRS)
$(SUBDIRS):
    $(MAKE) -C $@ $(MAKECMDGOALS)

Upvotes: 1

Related Questions