sigalor
sigalor

Reputation: 1369

Make multiple targets for all subdirectories

My directory structure is the following (of course the src/ subdirectories also contain files, but these are not important right now):

examples/
├───testprog1/
│   ├───bin/
│   ├───obj/
│   ├───src/
│   └───Makefile
├───testprog2/
│   ├───bin/
│   ├───obj/
│   ├───src/
│   └───Makefile
└───Makefile

The Makefile's in testprog1/ and testprog2/ look similar to this one:

OBJECTS_FILES=$(subst .cpp,.o,$(subst src/,obj/,$(wildcard src/*.cpp)))

bin/testprog1.exe: $(OBJECTS_FILES)
    g++ -o $@ $^

obj/%.o: src/%.cpp
    g++ -c -o $@ $^

clean:
    rm -f obj/*.o
    rm -f bin/meanTest.exe

They work perfectly fine alone, but if I want to build all examples at once, it would be better to use the Makefile in examples/ for that. What should it look like? Of course, it has to have the targets all and clean it will execute for all subdirectories. I also would like to avoid for-loops because I heard that they prevent make from using parallel processing.

Upvotes: 0

Views: 435

Answers (1)

John
John

Reputation: 3520

You can make a recipe run in the background by appending an & to the end, which would allow you to build in parallel, but that's messy as your target could complete before the background tasks have finished running, which could cause dependency issues, so we'll steer clear of that.

A better solution would be to create a new rule for each subdir:

.PHONY: testprog1 testprog2

testprog1 testprog2:
    $(MAKE) -C $@ $(MAKECMDGOALS)

all clean: testprog1 testprog2 

If you do a make clean, then $(MAKECMDGOALS) will be clean. It will build both testprog1 and testprog2 with this target. Notice that because testprog1 and testprog2 are directory names, you have to declare them as phonies, as their timestamp will change when you build them.

You could also specify the target as %: testprog1 testprog2 if you wanted any command (save testprog1 or testprog2) to be passed down to the submakes.

Upvotes: 1

Related Questions