Reputation: 42
Our project uses Makefiles with the following type of rule for each multi-directory sub-make:
DIRS = lib audio conf parser control
all: $(DIRS)
@for DIR in $(DIRS); \
do \
( cd $$DIR; $(MAKE) $(MFLAGS) all; ) \
done
If any file fails to compile in one of the leaf makes, the build stops in that directory - but the rest of the make continues. How do I set up these Makefiles so the first error at any level will stop the entire make?
Thanks
Upvotes: 2
Views: 12646
Reputation: 29222
From the for loops section of the bash manual:
The return status is the exit status of the last command that executes.
So, you do not need to capture return statuses. You need your recipe to fail if any sub-make fails:
DIRS = lib audio conf parser control
all: $(DIRS)
@for DIR in $(DIRS); do \
$(MAKE) -C $$DIR $(MFLAGS) all || exit 1; \
done
But it would be much better to have individual recipes per directory, instead of a single for loop:
DIRS = lib audio conf parser control
all: $(DIRS)
.PHONY: all $(DIRS)
$(DIRS):
$(MAKE) -C $@ $(MFLAGS) all
This way, if a sub-make fails, it is the complete rule's recipe that fails and make stops. Note the .PHONY
special target, in this case it is needed because you want to run the recipe, even if the directory already exists.
There is another advantage with this structure: if you run make in parallel mode (make -j N
) it will launch several sub-makes simultaneously instead of just one with the for loop. And each sub-make, in turn, will launch several recipes in parallel, up to N
jobs. On a multi-processor or multi-core architecture the speed-up factor can be significant.
But this advantage can become a drawback if your project is not parallel safe, that is, if the order of processing of your directories matters and is not properly defined in the makefiles. If you are in this situation you can add a:
.NOTPARALLEL:
special target at the beginning of your main makefile to tell make. But it would be better to explicitly define the inter-directories dependencies. And if you do not know how to do this, please ask another question.
Upvotes: 5
Reputation: 42
I found the answer in this question's answer: I have to rewrite to capture the return status of each submake.
Upvotes: 0