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 have var 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)).
  • 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