# allows parallel make across directories and lets make -k and -q work
# correctly.
+# We need the $(eval) function and order-only prerequisites, which are
+# available in GNU make 3.80. That also happens to be the version
+# where the .VARIABLES variable was introduced, so this is a simple check.
+ifndef .VARIABLES
+$(error GNU make 3.80 or newer is required. You are using version $(MAKE_VERSION))
+endif
+
# This function is only for internal use below. It should be called
-# with $(eval). It will set up a target so that it recurses into
-# subdirectories.
+# using $(eval). It will set up a target so that it recurses into
+# a given subdirectory. Note that to avoid a nasty bug in make 3.80,
+# it is important that the expansion of this function not exceed about
+# 200 bytes. This is why we make it apply to just one subdirectory at a
+# time, rather than to a list of subdirectories.
# $1: target name, e.g., all
-# $2: list of subdirs
+# $2: subdir name
# $3: target to run in subdir, usually same as $1
define _create_recursive_target
-.PHONY: $(patsubst %,$(1)-%-recursive,$(2))
-$(1): $(patsubst %,$(1)-%-recursive,$(2))
-$(2:%=$(1)-%-recursive):
- $$(MAKE) -C $$(patsubst $(1)-%-recursive,%,$$@) $(3)
+.PHONY: $(1)-$(2)-recurse
+$(1): $(1)-$(2)-recurse
+$(1)-$(2)-recurse:
+ $$(MAKE) -C $(2) $(3)
endef
# Note that the use of $$ on the last line above is important; we want
-# those variables/functions to be evaluated when the rule is run, not
-# when the $(eval) is run to create the rule. In the case of
-# $$(MAKE), this is necessary to get make -q working.
+# $(MAKE) to be evaluated when the rule is run, not when the $(eval) is run
+# to create the rule. This is necessary to get make -q working.
-# Call this function in a makefile. In the normal case it doesn't
-# need any arguments.
+# Call this function in a makefile that needs to recurse into subdirectories.
+# In the normal case all arguments can be defaulted.
# $1: targets to make recursive (defaults to list of standard targets)
# $2: list of subdirs (defaults to SUBDIRS variable)
-# $3: target to run in subdir (defaults to $1)
-recurse = $(foreach target,$(if $1,$1,$(standard_targets)),$(eval $(call _create_recursive_target,$(target),$(if $2,$2,$(SUBDIRS)),$(if $3,$3,$(target)))))
-
-# We need the $(eval) function and order-only prerequisites, which are
-# available in GNU make 3.80. That also happens to be the version
-# where the .VARIABLES variable was introduced, so this is a simple
-# check.
-ifndef .VARIABLES
-$(error GNU make 3.80 or newer is required. You are using version $(MAKE_VERSION))
-endif
+# $3: target to run in subdir (defaults to current element of $1)
+recurse = $(foreach target,$(if $1,$1,$(standard_targets)),$(foreach subdir,$(if $2,$2,$(SUBDIRS)),$(eval $(call _create_recursive_target,$(target),$(subdir),$(if $3,$3,$(target))))))
##########################################################################