Work around make 3.80 bug with long expansions of $(eval).

3.80 breaks if the expansion of $(eval) is long enough to require expansion
of its internal variable_buffer.  For the purposes of $(recurse) that means
it'll work so long as no single evaluation of _create_recursive_target
produces more than 195 bytes.  We can manage that by looping over
subdirectories outside the call instead of complicating the generated rule.
This coding is simpler and more readable anyway.

Or at least, this works for me.  We'll see if the buildfarm likes it.
This commit is contained in:
Tom Lane 2010-11-14 12:50:06 -05:00
parent 2138c701a3
commit 1bd2012149
1 changed files with 27 additions and 26 deletions

View File

@ -549,38 +549,39 @@ install-strip:
# allows parallel make across directories and lets make -k and -q work
# correctly.
# 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.
# $1: target name, e.g., all
# $2: list of subdirs
# $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)
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.
# Call this function in a makefile. In the normal case it doesn't
# need any arguments.
# $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.
# 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
# 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: subdir name
# $3: target to run in subdir, usually same as $1
define _create_recursive_target
.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
# $(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 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 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))))))
##########################################################################
#