To demonstrate a major difference of how make treats single-line recipe than that of .ONESHELL
-multiple-line recipe, I will use a sed
command, where, we assume, that either of the following:
sed -e 'p; p'
sed -e 'p
p'
are mostly equivalent. Right?
What we find, however, is that Make fails only on the single-line recipe.
Yeah! That's right. Make handles perfectly fine the multiple-line version (due to .ONESHELL
, of course), but cannot do the same for a single-line recipe.
It defies common-sense, but here is the proof.
The Makefile:
.ONESHELL :
# Define a MULTIPLE-line recipe.
define define_cmd_foo
all : cmd_foo = echo xxx | sed -ne '
s/xxx/yyy/
p'
endef
# Define a SINGLE-line recipe.
define define_cmd_bar
all : cmd_bar = echo xxx | sed -ne 's/xxx/yyy/; p'
endef
# cmd_foo is multiple-line (3 line) recipe:
# echo xxx | sed -ne '
# s/xxx/yyy/
# p'
$(define_cmd_foo)
# cmd_foo is a one and single-line recipe:
# echo xxx | sed -ne 's/xxx/yyy/; p'
$(define_cmd_bar)
# This is a 1st file in a double-colon (linked list of) target 'all'.
# This will exeucte a multipe-line recipe.
all ::
$(cmd_foo)
# This is a 2nd file in a double-colon (linked list of) target 'all'.
# This will exeucte a single-line recipe.
all ::
$(cmd_bar)
Executing, we get:
echo xxx | sed -ne '
s/xxx/yyy/
p'
yyy
echo xxx | sed -ne 's/xxx/yyy/
/bin/sh: 1: Syntax error: Unterminated quoted string
makefile:34: recipe for target 'all' failed
make: *** [all] Error 2
Can you see here 2 commands?
The first command executes a multiple-line recipe, and succeeds.
In fact, the output for the first recipe: yyy
, is exactly what we expected.
Any output, from the 5th line and the following lines - of the output - above, belongs to the execution of the other single-line recipe, which looks like something went wrong there. Very wrong!
Any reason, why a perfect good recipe goes well with .ONESHELL
for a multiple-line version, but fails in a plain one-line version?