On 2023-06-07 03:23, Bartłomiej Wójcik wrote: > Hi, > The GNU make documentation states: > > *define myrule > target: > echo built > endef > > $(myrule) > * > > *The above makefile results in the definition of a target ‘target’ with > prerequisites ‘echo’ and ‘built’, as if the makefile contained target: echo > built, rather than a rule with a recipe. Newlines still present in a line > after expansion is complete are ignored as normal whitespace.*
The documentation around that example treats it as a line separation issue. It can be explained like this: the result of an expansion at the top-level is not automatically treated as Make syntax. For instance, the following example also doesn't work, yet does not have any line ending issue: ASSIGNMENT := A := B $(info $(ASSIGNMENT)) # prints A := B $(ASSIGNMENT) $(info $(A)) # hoping to see B printed Instead, the curious error message is produced against the $(ASSIGNMENT) line: A := B Makefile:5: *** empty variable name. Stop. If you wish the expansion of $(...) syntax to be correctly treated as Makefile syntax and incorporated into the compilation, you must use the $(eval) operator: ASSIGNMENT := A := B $(info $(ASSIGNMENT)) # prints A := B $(eval $(ASSIGNMENT)) $(info $(A)) # hoping to see B printed Now the output is: A := B B make: *** No targets. Stop. The documentation does state that the way to do it $(eval). The thing with the newlines and the recipe line being confused as a prerequisite is correct, of course, but in a way secondary. The main concept is that simply by evaluating a variable, or other expansion, outside of any construct, you do not induce re-evaluation of syntax. You must evaluate the $(eval ...) specifically. Expansions do substitute into syntax, but only in specific places under control of that syntax. So this won't work either: ASSIGNMENT_OP = := A $(ASSIGNMENT_OP) B $(info $(A)) Although $(ASSIGNMENT_OP) evaluates to :=, by the time that happens it is too late; the A $(ASSIGNMENT_OP) B line was not recognized as being assignment syntax.