GNU Make:普通破折号有时会在多行变量中被抑制

问题描述 投票:0回答:1

我正在尝试使用 GNU Make v4.4.1 为 YAML 文件头定义一个多行变量,例如:

#foo
---

这个想法是将标题回显到配方内的文件。由于我不知道的原因,在某些情况下破折号会被剥离。

这是 MWE:

.ONESHELL:

define dashes
# dashes below stripped off
---
endef

define dashes_hex
# hex dashes below kept
\x2d\x2d\x2d
endef

define only_dashes
---
endef

define dashes_first
---
# dashes above kept
endef

.PHONY: a b c d

a:
    @echo -e "a>$(dashes)<"

b:
    @echo -e "b>$(dashes_hex)<"

c:
    @echo -e "c>$(only_dashes)<"

d:
    @echo -e "d>$(dashes_first)<"

测试:

$ make a b c d
a># dashes below stripped off
<
b># hex dashes below kept
---<
c>---<
d>---
# dashes above kept<

如您所见:

  • 情况 b) 解决方法是使用相应的十六进制值而不是普通破折号字符,
  • 情况 c) 正确打印了单行普通破折号,
  • 情况 d) 第一行的普通破折号打印正确。

简单的破折号和 Make 有什么特别之处? 为什么情况c和d有正确的结果?

makefile gnu-make multiline
1个回答
0
投票

首先,当您尝试调试 makefile 时,切勿使用

@
作为行前缀。 查看 make 正在调用的命令对于理解其行为至关重要。

接下来,您不应该在需要可移植的 makefile 中使用

echo -e
。 事实上,
echo
在可移植 shell 脚本中唯一可以做的就是打印简单的字符串:
echo
没有标准化的选项。 有些版本支持
-e
,有些不支持。

如果您需要打印格式化输出,您应该使用

printf
程序来代替便携。

第三,如果你想知道 GNU Make 中变量的值是什么,请使用

info
函数来打印它们,而不是使用配方;这可以让您知道值是什么,而无需 shell 干扰。 如果添加:

$(info dashes:|$(dashes)|)
$(info dashes_hex:|$(dashes_hex)|)
$(info only_dashes:|$(only_dashes)|)
$(info dashes_first:|$(dashes_first)|)

您将看到 make 对于每个变量都有正确/预期的内容:

dashes:|# dashes below stripped off
---|
dashes_hex:|# hex dashes below kept
\x2d\x2d\x2d|
only_dashes:|---|
dashes_first:|---
# dashes above kept|

这意味着问题不在于变量值错误,而在于配方的创建或运行。

我认为问题在于

.ONESHELL
并不是真正设计来处理您正在创建的情况。 如果您使用包含换行符的变量,则 make 会认为配方中的每一行都是一个单独的“命令”。 因此,它将检查每一行,看看它是否以
@
-
开头,如果是,它们将被删除。 请参阅文档中的此段落:

作为一项特殊功能,如果 SHELL 被确定为 POSIX 风格的 shell,则在处理配方之前,将删除“内部”配方行中的特殊前缀字符。此功能旨在允许现有 makefile 添加 .ONESHELL 特殊目标,并且无需大量修改即可正常运行。由于特殊前缀字符在 POSIX shell 脚本中的行开头是不合法的,这并不是功能上的损失。

不幸的是,您似乎发现了一个漏洞,本段的最后一句话实际上并不正确。

© www.soinside.com 2019 - 2024. All rights reserved.