GNU make manual 翻译( 一百三十五)
继续翻译
If `.ONESHELL' is provided, then only the first line of the recipe will be checked for the special prefix characters (`@', `-', and `+'). Subsequent lines will include the special characters in the recipe line when the `SHELL' is invoked. If you want your recipe to start with one of these special characters you'll need to arrange for them to not be the first characters on the first line, perhaps by adding a comment or similar. For example, this would be a syntax error in Perl because the first `@' is removed by make: .ONESHELL: SHELL = /usr/bin/perl .SHELLFLAGS = -e show : @f = qw(a b c); print "@f\n"; However, either of these alternatives would work properly: .ONESHELL: SHELL = /usr/bin/perl .SHELLFLAGS = -e show : # Make sure "@" is not the first character on the first line @f = qw(a b c); print "@f\n"; or .ONESHELL: SHELL = /usr/bin/perl .SHELLFLAGS = -e show : my @f = qw(a b c); print "@f\n"; As a special feature, if `SHELL' is determined to be a POSIX-style shell, the special prefix characters in "internal" recipe lines will _removed_ before the recipe is processed. This feature is intended to allow existing makefiles to add the `.ONESHELL' special target and still run properly without extensive modifications. Since the special prefix characters are not legal at the beginning of a line in a POSIX shell script this is not a loss in functionality. For example, this works as expected: .ONESHELL: foo : bar/lose @cd $(@D) @gobble $(@F) > ../$@ Even with this special feature, however, makefiles with `.ONESHELL' will behave differently in ways that could be noticeable. For example, normally if any line in the recipe fails, that causes the rule to fail and no more recipe lines are processed. Under `.ONESHELL' a failure of any but the final recipe line will not be noticed by `make'. You can modify `.SHELLFLAGS' to add the `-e' option to the shell which will cause any failure anywhere in the command line to cause the shell to fail, but this could itself cause your recipe to behave differently. Ultimately you may need to harden your recipe lines to allow them to work with `.ONESHELL'.
如果提供了 .ONESHELL, 那么只有片段的第一行才会被进行特殊前缀字符检查(@,-,+)。后续的行会在shell激活的时候包含这些片段行中的特殊符号。如果你想要你的片段开始于这些特殊符号,你需要是的它们不要成为第一行的第一个字符,比如通过加入一个注释之类。例如,在Perl 中,由于@ 被移出,可能导致语法错误:
.ONESHELL:
SHELL = /usr/bin/perl
.SHELLFLAGS = -e
show :
@f = qw(a b c);
print "@f\n";
然而, 下面两者都会正常工作:
.ONESHELL:
SHELL = /usr/bin/perl
.SHELLFLAGS = -e
show:
# Make sure "@" is not the first character on the first line
@f = qw(a b c);
print "@f\n";
或者
.ONESHELL:
SHELL = /usr/bin/perl
.SHELLFLAGS = -e
show :
my @f = qw(a b c);
print "@f\n";
作为一项特殊的功能, 如果shell 是一个 POSIX-类型的shell, 在片段行内部的特殊前缀字符将在片段被执行前移出。此功能致力于允许现存的makefile通过加入.ONESHELL 特殊目的后不需要代价太大的改变仍然可以正常运行。 因为在POSIX shell中,特殊的前缀字符在一行的开头是不合法的, 这并不是一个功能性的顺损失。例如,如下可以很好地工作:
.ONESHELL:
foo : bar/lose
@cd $(@D)
@gobble $(@F) > ../$@
即便是有这个特殊功能, 带有.ONESHELL 的makefile,将会表现得有所不同。例如,通常如果任何片段中的任何一行失败,会导致规则失败并且没有其它行再被执行。在使用 .ONESHELL的时候, 除了片段最后一个行的失败,其它的失败不会被通知到 make。你可以改变 .SHELLFLAGS 标志,加入 -e 选项给shell,此时任何错误都会导致片段报错,但是这个行为本身能造成你的片段行为异常。
基本上你需要强化你的片段行,使它们能够适应 .ONESHELL
后文待续