Reputation: 17420
I'm trying to make sense out of the multi-line define
directive of GNU make and I cannot. Example:
define A
1
2
endef
all:
@echo W=$(word 1,$(A))
Running make
produces a result I have expected the least:
W=1
make: 2: Command not found
make: *** [all] Error 127
It appears that part of $(A)
has spilled outside the $(word)
function.
Is it a bug or intended behavior? If the "spill" is intentional, how does it really works?
P.S. GNU make v3.81 on Linux/x64
Upvotes: 2
Views: 3220
Reputation: 15483
The thing to remember here is that make stores each recipe as a single recursive variable. At the point that make decides that it must run your recipe, it expands that variable. Make then passes each line in the resulting expansion to a separate shell, stopping if any of those shell executions return an error.
In your example, before running anything make expands @echo W=$(word 1,$(A))
.
$(A)
becomes 1¶2
(dunno what this looks like on your browser, but I'm using ¶
to represent a newline character)1¶2
is a single word as far as make is concerned, so $(word 1,1¶2)
naturally expands to 1¶2
(can you see where this is going yet?)@echo W=1¶2
. Make dutifully passes the first line of this to the shell (without the @
as that is special to make). The shell executes echo W=1
.2
in a new shell.2
.So, yes, expected behaviour.
[Warning: slight simplification in the above where I gloss over the bit where make is able to elide the shell and invoke the command itself if the string has no shell metacharacters in it]
Upvotes: 4
Reputation: 80931
The $(word)
function is splitting on spaces. Not whitespace, spaces.
There are no spaces in your A
macro so nothing gets split.
Add a trailing space on the 1
line or a leading space on the 2
line and you get your expected behaviour.
This is consistent across GNU make 3.81, 3.82, 4.0, and 4.1 in some quick testing here.
The reason you see the "spill" as you called it is because of how the define is expanded. It is expanded literally, newline and all. (Think template expansion.)
So make expands the define into the call to $(word 1,...)
then expands that result (the whole define including the newline) into the recipe template and ends up with two lines that it executes as the recipe.
Consider a macro like this:
define somecommands
echo foo
echo bar
echo baz
endef
all:
$(somecommands)
What would you expect to happen here? How many lines is the body of all
? How many shells are run here? What commands are executed? The answer is three lines, three shells and three echo commands.
If the newlines weren't counted then you would effectively run echo foo echo bar echo baz
in one command and get foo echo bar echo baz
as output instead of the expected (and far more useful) foo
, bar
, and baz
on three different lines.
Upvotes: 2