I'm seeing unexpected results for target-specfic variables in GNU make.
What I want is to set a target-specific variable that affects dependencies. I can use .SECONDEXPANSION
to achieve that.
some-target: DEP := debug-dep
debug: some-target
.SECONDEXPANSION:
some-target: $$(DEP)
@echo $^
debug-dep:
make debug
prints debug-dep
.
Now I read that make defines target-specific variables for descendant rules:
When you define a target-specific variable that variable value is also in effect for all prerequisites of this target, and all their prerequisites, etc.
But when I change my makefile to have the variable set on "parent" target:
debug: DEP := debug-dep
debug: some-target
.SECONDEXPANSION:
some-target: $$(DEP)
@echo $^
debug-dep:
and do make debug
I get a blank line.
This seems to contradict the documented behavior of target-specific variables. Is there something that I am missing?
This is sort of similar to make: Using target specific variables in prerequisites, but what I am doing isn't working.
Makefile Syntax The targets are file names, separated by spaces. Typically, there is only one per rule. The commands are a series of steps typically used to make the target(s). These need to start with a tab character, not spaces.
The file name of the target of the rule. If the target is an archive member, then ' $@ ' is the name of the archive file. In a pattern rule that has multiple targets (see Introduction to Pattern Rules), ' $@ ' is the name of whichever target caused the rule's recipe to be run.
An attribute is a specific value on a variable. For instance, the variable Student grade has two attributes: pass and fail . Or, the variable agreement might be defined as having five attributes: 1 = strongly disagree.
I believe the issue here is that target-specific variables are not set until the targets are being run (if you add @echo '$(DEP)'
to your some-target
body in that second case you will see that it is set) but that second expansion happens immediately after the initial read-in phase.
I was going to say that I'm actually surprised that this works in the first case at all (and speculate as to why) but then I pulled up the manual for a minute and while reading about .SECONDEXPANSION
I found the following:
[T]he true power of this feature only becomes apparent when you discover that secondary expansions always take place within the scope of the automatic variables for that target. This means that you can use variables such as $@, $*, etc. during the second expansion and they will have their expected values, just as in the recipe. All you have to do is defer the expansion by escaping the $. Also, secondary expansion occurs for both explicit and implicit (pattern) rules.
Which explains your behaviour exactly. The expansion only sees variables set in the scope of the target and the prerequisite inheriting only happens at target evaluation time (since it depends on target prerequisites).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With