3

In gnu make, is there a way to get hold of the original target that initiated the whole chain and lead the execution to the current recipe?

.PHONY : all clean common
all: common
clean: common

common:
    @echo $@
    @echo $(MAKECMDGOALS)
    @for a in $$(ls); do \
        if [ -d $$a ]; then \
            echo -C $$a $(MAKECMDGOALS); \
            #$(MAKE) -C $$a $(MAKECMDGOALS); \
        fi; \
    done;
    @echo "Done!"

As in the above example, when I run the 'make all' or 'make clean', I can use $(MAKECMDGOALS) to tell which target was passed to make from the command line. However, if someone calls it as 'make clean all', then 'common' is called once and we get 'make: Nothing to be done for `clean'.'.

So, is there a way to call 'common' for every time it is referenced as prerequisite for a target and also work out the originating target name so it can be passed into the next make? Even though 'common' is a PHONY target, it is only called once and I am not sure why.

I've got below alternatives but and I think the first one is the neatest

makefile 1

just_a_func = @echo "just_a_func from " $(1)

.PHONY : all clean
all:
    @echo $@ " enter"
    $(call just_a_func, $@)

clean:
    @echo $@ " enter"
    $(call just_a_func, $@)

makefile 2

.PHONY : all clean common
all:
    @echo $@ " enter"
    $(MAKE) -f makefile common

clean:
    @echo $@ " enter"
    $(MAKE) -f makefile common

common:
    @echo $@ " enter"
Community
  • 1
  • 1
abdus_salam
  • 738
  • 2
  • 7
  • 19
  • Is this the entirety of some top-level "driver" makefile that needs to simply delegate to sub-directory makefiles? – Etan Reisner May 19 '15 at 18:55
  • This shouldn't run the `common` recipe twice though. Does adding `touch $@` to the recipe fix that problem? – Etan Reisner May 19 '15 at 18:56
  • If someone invokes `make clean all`, then... what do you want Make to do? – Beta May 19 '15 at 23:24
  • @EtanReisner, you are right, this runs the 'common' once and that is one of my actual questions but had miss-expressed in the original question. Corrected now. – abdus_salam May 20 '15 at 16:06
  • @Beta, what I want is to run 'common' for every target it is related to. I'd also need to know the original target which triggers this so it can be passed down to the next 'make'. I've updated the question to reflect this. – abdus_salam May 20 '15 at 16:09
  • 1
    I don't believe you can get make to run a given target more than once. Using a [canned recipe](http://www.gnu.org/software/make/manual/make.html#Canned-Recipes) is probably the best idea here. (Essentially what you have in makefile 1.) (Be careful with spaces around commas in make calls. It doesn't always strip them.) As for the original target thing the closest you can get are [target-specific variables](http://www.gnu.org/software/make/manual/make.html#Target_002dspecific). – Etan Reisner May 20 '15 at 16:17

1 Answers1

1

It strikes me as there are two questions here, the one in the title and another one slipped in when elaborating the problem.

In answer to how to the question in the title: getting hold of the target that leads to a change, use remake.

For example, using the Makefile you provided:

$ remake -X -f Makefile
GNU Make 4.1+dbg0.91
...
Reading makefiles...
Updating makefiles....
Updating goal targets....
 File 'PHONY' does not exist.
   File 'all' does not exist.
-> (/tmp/Makefile:5)
common:
remake<0> T
=>#0  common at /tmp/Makefile:5
  #1  all at /tmp/Makefile:2
  #2  PHONY at /tmp/Makefile:1
remake<1> quit

$ remake -X -f Makefile clean
GNU Make 4.1+dbg0.91
...
Reading makefiles...
Updating makefiles....
Updating goal targets....
 File 'clean' does not exist.
-> (/tmp/Makefile:5)
common:
remake<0> T
=>#0  common at /tmp/Makefile:5
  #1  clean at /tmp/Makefile:3
remake<1>

Above we so happened to start at the target we want to inspect. If that's not the case you can use the "breakpoint" command to set a breakpoint, and "continue" to run until you hit that target.

rocky
  • 7,226
  • 3
  • 33
  • 74