如何正确转义Makefile的数据?

Lek*_*eyn 37 bash makefile escaping

我正在config.mk使用一个将由Makefile使用的bash脚本动态生成.该文件构造为:

cat > config.mk <<CFG
SOMEVAR := $value_from_bash1
ANOTHER := $value_from_bash2
CFG
Run Code Online (Sandbox Code Playgroud)

如何确保生成的文件确实包含内容$value_from_bash*,而不是扩展/解释的内容?我可能需要逃避$$$\\\,但是否有其他字符需要进行转义?也许有一个我没有听说过的特殊字面作业?

太空似乎也很麻烦:

$ ls -1
a b
a
$ cat Makefile
f := a b
default_target:
    echo "$(firstword $(wildcard ${f}))"
$ make
a
Run Code Online (Sandbox Code Playgroud)

如果我使用f := a\ b它的工作原理(使用引号f := 'a b'也不起作用,makefile只会将其视为常规字符)

Lek*_*eyn 52

好的,事实证明,Makefile几乎不需要自行转义,但shell解释器执行的命令需要转义.

在Makefile中具有特殊含义且需要转义的字符是:

  • 锐利(#评论)成为\#
  • 美元($变量的开头)变成了$$

新行不能插入变量中,但为了避免破坏Makefile的其余部分,请在前面添加反斜杠,以便忽略换行符.

太糟糕了,反斜杠本身无法转义(\\仍将是,\\而不是\你想象的那样).这使得无法在字符串的末尾放置文字斜杠,因为它将使用换行符或后续注释的散列值.一个空格可以放在行的末尾,但也可以放在变量本身中.

配方本身被解释为一个shell命令,没有任何花哨的转义,所以你要自己逃避数据,只是想象你正在编写一个shellcript并从其他文件中插入变量.这里的策略是把变量单引号和逃避只能''\''(关闭串,插入文字',并开始一个新的字符串).示例:mornin' all变为'morning'\'' all'等同于"morning' all".

第一个字+通配符问题是由于其中包含空格的文件名被视为单独的文件名firstword.此外,wildcard使用\so 扩展转义x\ y是匹配作为一个单词,x y而不是两个单词.


Meh*_*dad 5

似乎在互联网上找不到这个问题的完整答案,所以我终于坐下来,为Windows案例弄清楚了。

具体来说,“视窗案”指的是在Windows中是有效的文件名,这意味着它们包含字符\/*?"^<>|,或换行符。对于Make而言,它也意味着\并且/都被视为有效的目录分隔符。

一个例子将比我能解释的更好。基本上,如果您尝试匹配此文件路径:

Child\a$b  {'}(a.o#$@,&+=~`),[].c
Run Code Online (Sandbox Code Playgroud)

然后,您必须编写以下规则:

all: Child\\a$$b\\\ \\\ {'}(a.o\#$$@,&+=~`),[].o

%.o: %.c
    $(CC) '$(subst ','"'"',$(subst \,,$(subst \\,/,$+)))'
Run Code Online (Sandbox Code Playgroud)

盯着它看了很长时间,它开始有点儿遥不可及了。

这在我的MSYS2环境中有效,因此我认为它是正确的。