Search code examples
getmakefiledependenciescall

Chaining dependencies from submake to its parent


I made a small example to illustrate my issue:

I have several projects and one principal Makefile to rule them all.

/+
 |+ Makefile
 |+ Project A
 |  + Makefile
 |+ Project B
 |  + Makefile 
 |...

The parent Makefile looks like this:

DUMMY := $(shell $(MAKE) -C a deps) $(shell $(MAKE) -C b deps)

.PHONY: all clean

all: out.zip
    @echo Operation Done!

a/a.zip: $(addprefix a/,$(shell cat a/deps))
    $(MAKE) -C a $(notdir $@)

b/b.zip: $(addprefix b/,$(shell cat b/deps))
    $(MAKE) -C b $(notdir $@)

out.zip: a/a.zip b/b.zip
    zip $@ $^ 

clean: 
    $(MAKE) -C a clean
    $(MAKE) -C b clean

And here one of the sub-makefile (inside each sub-projects):

C   = $(notdir $(shell pwd))
SRC = $(addsuffix .c, $(addprefix $(C), 1 2 3 4))
OBJ = $(patsubst %.c, %.o, $(SRC))

all: $(C).zip 

$(SRC): %.c : 
    touch $@

$(OBJ): %.o : %.c  
    cp $< $@

$(C).zip: $(OBJ)
    zip $@ $^

clean: 
    -rm -f *.o *.zip deps
    $(MAKE) $(SRC)
deps: 
    @echo $(SRC) > $@

.PHONY: all clean deps

My question is quite simple: How to avoid calling the sub-makefile in order to get all the dependancies. Indeed, when I modify one of the source file inside a sub-project, the main Makefile is unable to know whether or not the target needs to be rebuilt.

I also found that I can call make with the options $(MAKE) -C<dir> -n -s which allow me to write my rules like this:

a/a.zip: $(if $(shell make -C a -n -s), $(shell rm a/a.zip),)
    $(MAKE) -C a $(notdir $@)

b/b.zip: $(if $(shell make -C b -n -s), $(shell rm b/b.zip),)
    $(MAKE) -C b $(notdir $@) 

But I'm sure this is not the best solution !

Any suggestions ?


Solution

  • You can share your subprojects sources, $(SRCPRJ1) and $(SRCPRJ2), in another file (a config file) that would be loaded by the principal Makefile too. Or just redo them in the principal, instead.

    After that, put them as the prerequisites of your targets in the principal Makefile:

    a/a.zip: $(SRCPRJ1)
        $(MAKE) -C a $(notdir $@)
    
    b/b.zip: $(SRCPRJ2)
        $(MAKE) -C b $(notdir $@)
    

    Thus, the recipes a/a.zip and b/b.zip will only be parsed if its dependencies have been updated.

    That worked to me.