gnu make - How do you define pattern-specific variables for makefile pattern rules containing a patterned prerequisite? -
i understand can define pattern-specific variables rules no prerequisites, this:
%.o: var = 2
this set variable var
2 recipes apply targets ending in .o. stated in gnu make documentation. how define pattern-specific variable pattern rules contain pattern prerequisite, this:
%.o: %.c
say have section of makefile:
%.o: %.c (recipe here) %.o: %.b (recipe here)
i want define pattern-specific variable %.o: %.b
rule, don't see how (if it's possible). i'd this, of course doesn't work:
%.o: %.c (recipe here) %.o: %.b: var = 2 (recipe here)
is there way this?
you can set variable targets, not rules. %.o: %b
rule %.o
target pattern (hence "pattern-specific" name).
the usual way solve ether hard coding values in recipes or using rule-specific flags (maybe cvar
, bvar
in case).
edit: scratch that. came workaround.
it can done leveraging variables' recursive evaluation.
all: a.o b.o c.o $(shell touch a.xx b.yy c.zz) ## # create rule-specific variable... rules # # @param 1 target. # @param 2 prerequisite. # @param 3 variable name. # @param 4 variable value. # rule-var = $(eval $(rule-var-body)) define rule-var-body $1: private $3 = $$(if $$(<:$2=),$(or $(value rule-var-$1-$3),$(value $3)),$4) $2: $3 = $4 rule-var-$1-$3 = $$(if $$(<:$2=),$(or $(value rule-var-$1-$3),$(value $3)),$4) endef var = $(var_default) # declare couple of test values $(call rule-var,%.o,%.x,var,x-value) $(call rule-var,%.o,%.y,var,y-value) var_default := z-value echo_rule_recipe = @echo -e '$@: $^\t(var = $(var))' %.o: %.x $(echo_rule_recipe) %.o: %.y $(echo_rule_recipe) %.o: %.z $(echo_rule_recipe) %.x: %.xx $(echo_rule_recipe) %.y: %.yy $(echo_rule_recipe) %.z: %.zz $(echo_rule_recipe)
the output is:
a.x: a.xx (var = x-value) a.o: a.x (var = x-value) b.y: b.yy (var = y-value) b.o: b.y (var = y-value) c.z: c.zz (var = z-value) c.o: c.z (var = z-value)
the brains of operation macro rule-var
. wrap variable value in prerequisite matching if-else
expression. expression saved in rule-var-$1-$3
variable other rule-specific values.
$$(if $$(<:$2=),$(or $(value rule-var-$1-$3),$(value $3)),$4)
deobfuscation:
$$(if $$(<:$2=),
test first prerequisite value ($<
) replacing it's pattern ($2
) empty string.
if pattern doesn't match, use
$(or $(value rule-var-$1-$3),$(value $3))
. workaround global variable shadowing. in example%.o: %.c
doesn't havevar
declared should use global value both rules share same target, it's not visible. both referenced value , single$
expands expression during variable substitution phase. result neat ,or
free.- use
$(value rule-var-$1-$3)
if it's nonzero. function has been called before target , variable name. - otherwise use variable's global value (
$(value $3)
).
- use
otherwise use value provided (
$4
).
unfortunately, when inherited, if-else monstrosity won't expand it's declared private
, fixed straightforward second rule.
in example following 3 rules declared.
%.o: private var = $(if $(<:%.y=),$(if $(<:%.x=),$(var_default),x-value),y-value) %.y: var = y-value %.x: var = x-value
limitations
even workaround, variable's global counterpart still shadowed. if need default value, assign before calling rule-var
. global value copied part of rule-specific variable not expanded until use.
Comments
Post a Comment