简体   繁体   English

如何正确转义Makefile的数据?

[英]How do I properly escape data for a Makefile?

I'm dynamically generating config.mk with a bash script which will be used by a Makefile. 我正在使用一个将由Makefile使用的bash脚本动态生成config.mk The file is constructed with: 该文件构造为:

cat > config.mk <<CFG
SOMEVAR := $value_from_bash1
ANOTHER := $value_from_bash2
CFG

How do I ensure that the generated file really contains the contents of $value_from_bash* , and not something expanded / interpreted? 如何确保生成的文件确实包含$value_from_bash*的内容,而不是扩展/解释的内容? I probably need to escape $ to $$ and \\ to \\\\ , but are there other characters that needs to be escaped? 我可能需要将$$$\\\\\\ ,但还有其他字符需要转义吗? Perhaps there is a special literal assignment I've not heard of? 也许有一个我没有听说过的特殊字面作业?

Spaces seems to be troublesome too: 太空似乎也很麻烦:

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

If I use f := a\\ b it works (using quotes like f := 'a b' did not work either, makefile just treats it as a regular character) 如果我使用f := a\\ b它可以工作(使用像f := 'a b'这样的引号也不起作用,makefile只是将它视为常规字符)

Okay, it turned out that Makefiles need little escaping for itself, but the commands which are executed by the shell interpreter need to be escaped. 好的,事实证明,Makefile几乎不需要自行转义,但shell解释器执行的命令需要转义。

Characters which have a special meaning in Makefile and that need to be escaped are: 在Makefile中具有特殊含义且需要转义的字符是:

  • sharp ( # , comment) becomes \\# 锐利( # ,评论)成为\\#
  • dollar ( $ , begin of variable) becomes $$ 美元( $ ,变量开头)变为$$

Newlines cannot be inserted in a variable, but to avoid breaking the rest of the Makefile, prepend it with a backslash so the line break will be ignored. 新行不能插入变量中,但为了避免破坏Makefile的其余部分,请在前面添加反斜杠,以便忽略换行符。

Too bad a backslash itself cannot be escaped ( \\\\ will still be \\\\ and not \\ as you might expect). 太糟糕了,反斜杠本身无法转义( \\\\仍然是\\\\而不是\\如你所料)。 This makes it not possible to put a literal slash on the end of a string as it will either eat the newline or the hash of a following comment. 这使得无法在字符串的末尾放置文字斜杠,因为它将使用换行符或后续注释的散列值。 A space can be put on the end of the line, but that'll also be put in the variable itself. 一个空格可以放在行的末尾,但也可以放在变量本身中。

The recipe itself is interpreted as a shell command, without any fancy escaping, so you've to escape data yourself, just imagine that you're writing a shellscript and inserting the variables from other files. 配方本身被解释为一个shell命令,没有任何花哨的转义,所以你要自己逃避数据,只是想象你正在编写一个shellcript并从其他文件中插入变量。 The strategy here would be putting the variables between single quotes and escape only ' with '\\'' (close the string, insert a literal ' and start a new string). 这里的策略是将变量放在单引号之间,只转义' with '\\'' (关闭字符串,插入文字'并开始一个新字符串)。 Example: mornin' all becomes 'morning'\\'' all' which is equivalent to "morning' all" . 例如: mornin' all变为'morning'\\'' all' ,相当于"morning' all"

The firstword+wildcard issue is caused by the fact that filenames with spaces in them are treated as separate filenames by firstword . 第一个字+通配符问题是由于其中带有空格的文件名被firstword视为单独的文件名。 Furthermore, wildcard expands escapes using \\ so x\\ y is matches as one word, xy and not two words. 此外, wildcard使用\\扩展转义,因此x\\ y匹配为一个单词xy而不是两个单词。

It seems that the full answer to this question is found nowhere on the internet , so I finally sat down and figured it out for the Windows case. 似乎这个问题的完整答案在互联网上找不到,所以我终于坐下来想出了Windows案例。

Specifically, the "Windows case" refers to file names that are valid in Windows, meaning that they do not contain the characters \\ , / , * , ? 具体来说,“Windows案例”是指在Windows中有效的文件名,这意味着它们包含字符\\/* , ? , " , ^ , < , > , | , or line breaks. It also means \\ and / are both considered valid directory separators for the purposes of Make. "^<>|或换行符。它还意味着\\/都被认为是有效的目录分隔符,用于Make。

An example will clear it up better than I can explain. 一个例子将比我能解释的更清楚。 Basically, if you are trying to match this file path: 基本上,如果您尝试匹配此文件路径:

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

Then you have to write these rules: 然后你必须写这些规则:

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

%.o: %.c
    $(CC) '$(subst ','"'"',$(subst \,,$(subst \\,/,$+)))'

Stare at it for a long time and it'll sort of start making some remote sense. 盯着它看了很长时间,它开始有点遥感。

This works in my MSYS2 environment, so I presume it is correct. 这适用于我的MSYS2环境,因此我认为它是正确的。

  1. I don't see how that makefile can work as you say. 我没有看到makefile如何像你说的那样工作。 A pattern rule cannot be the default. 模式规则不能是默认值。
  2. You're missing a `$` in `$(wildcard ...)`, so I think you haven't posted what you're really testing. 你错过了`$(通配符......)`中的`$`,所以我认为你还没有发布你真正测试的内容。
  3. You should escape newlines too. 你也应该逃避换行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM