On Sun, 2022-06-26 at 03:20 +0200, Bruno Haible wrote: > target: $(DEPS1) $(DEPS2) > command1 > > However, with -j, $(DEPS1) and $(DEPS2) are being made in parallel. > If this is not desired, I can transform this rule to > > target: $(DEPS1) > test -z "$(DEPS2)" || $(MAKE) $(DEPS2) > command1 > > or (equivalently?) > > target: $(DEPS1) > $(MAKE) target2 > target2: $(DEPS2) > command1 > .PHONY: target2 > > The question is: Are these two rewrites really equivalent? If not, > how do they differ, and what is the best practice?
I'm not sure either of these are equivalent, because they will not build "target" if the $(DEPS1) prerequisites are older but the $(DEPS2) prerequisites are newer than "target". Say DEPS1 = one and DEPS2 = two, and the modification times are one < target < two. Now in your original, "target" will be rebuilt because "two" is newer than it. But in both of your replacements, "target" will not be built because it doesn't list DEPS2 ("two") as a prerequisite. And in fact, because "target" is not built make won't even try to build DEPS2, so they won't get rebuilt at all unless some DEPS1 prerequisite makes "target" out of date. If we assume that this doesn't matter (maybe "target" is PHONY), then the only obvious difference to me is that in the first option, it's possible that the submake won't be run at all (if DEPS2 is empty) while in the second option you will always run a sub-make. If your makefiles have side-effects merely by being invoked (such as rebuilding included files or whatever) that could make a difference.