Fri 29 Jul 2005 08:31:21 PM UTC, original submission:
Consider the following GNUmakefile:
.PHONY: all all.prologue all.epilogue all.serial all.parallel
SECS = 3
all:: all.prologue
@echo ---- cmd1 ----
all:: all.serial all.parallel
@echo ---- cmd2 ----
all:: all.epilogue
@echo ---- cmd3 ----
all.prologue all.epilogue::
@echo start - $@; sleep $(SECS); echo end - $@
all.parallel:
@echo start - $@; sleep $(SECS); echo end - $@
This makefile will be executed using the following command:
make -j12
The intent of the makefile is to define certain actions which will occur first, then actions which will occur in serial/parallel, and then actions which will occur last. This allows us to maximize parallelism, while still supporting serial processing -- all within the same Makefile. This is defined by the following construct:
all:: all.prologue # first
@true
all:: all.serial all.parallel # serial & parallel
@true
all:: all.epilogue # last
@true
This allows us to do the following (greatly simplified):
all.prologue::
@mkdir output
all.parallel: $(TASKS) # generate output/* (parallel)
$(TASKS): ; generate $@ > output/$@
all.epilogue::
combine output/*
This works perfectly in version 3.76 of make using -j12, but no longer works in version 3.80 (and 3.78).
In version 3.76, the output from the makefile is:
>> make-3.76 -j12
start - all.prologue
end - all.prologue
---- cmd1 ----
start - all.serial
start - all.parallel
end - all.serial
end - all.parallel
---- cmd2 ----
start - all.epilogue
end - all.epilogue
---- cmd3 ----
In version 3.80, the dependencies of ALL the 'all' targets are evaluated prior to the first command:
>> make-3.80 -j12
start - all.prologue
start - all.epilogue
start - all.serial
start - all.parallel
end - all.prologue
end - all.epilogue
end - all.parallel
end - all.serial
---- cmd1 ----
---- cmd2 ----
---- cmd3 ----
In the GNUmake documentation I find the following regarding the order in which '::' targets are evaulated (emphasis added):
"When a target appears in multiple rules, all the rules must be the same type: all ordinary, or all double-colon. If they are double-colon, each of them is INDEPENDENT OF ALL THE OTHERS."
"Double-colon rules with the same target are in fact COMPLETELY SEPARATE from one another. EACH DOUBLE-COLON RULE IS PROCESSED INDIVIDUALLY, just as rules with different targets are evaluated."
Given that description, V3.76 is processing the Makefile correctly. Version 3.80 (and 3.78) is broken in that it processes the dependencies of ALL the 'all::' targets before launching the command for the first one. This violates the documented "INDEPENDENT OF ALL THE OTHERS" statement.
This bug is found at the end of the remake.c file in the update_file() function. If the following code is removed from the 3.80 version of remake.c, then the documented functionality is restored:
#if 0
THE FOLLOWING BREAKS DOCUMENTED '::' FUNCTIONALITY!
/* Process the remaining rules in the double colon chain so they're marked
considered. Start their prerequisites, too. */
for (; f != 0 ; f = f->prev)
{
struct dep *d;
f->considered = considered;
for (d = f->deps; d != 0; d = d->next)
status |= update_file (d->file, depth + 1);
}
#endif
I've attached the Makefile shown above if you require it to debug the problem.
srmadsen
|