变量赋值后的尾随注释颠覆比较

nob*_*bar 0 comments makefile gnu-make

在GNU make中,附加到变量赋值的尾随注释会阻止后续比较(via ifeq)正常工作.

这是Makefile ......

  A = a
  B = b ## trailing comment
  C = c

  RESULT :=

ifeq "$(A)" "a"
  RESULT += a
endif

ifeq "$(B)" "b"
  RESULT += b
endif

ifeq "$(C)" "c"
  RESULT += c
endif

rule:
    @echo RESULT=\"$(RESULT)\"
    @echo A=\"$(A)\"
    @echo B=\"$(B)\"
    @echo C=\"$(C)\"
Run Code Online (Sandbox Code Playgroud)

这是输出......

$ make
RESULT=" a c"
A="a"
B="b "
C="c"
Run Code Online (Sandbox Code Playgroud)

正如您从显示的值中看到的那样RESULT,ifeq受到分配中存在的注释的影响B.回应变量B,表明问题不是评论,而是介入空间.

显而易见的解决方案是在比较之前明确剥离空白,如此...

ifeq "$(strip $(B))" "b"
  RESULT += b
endif
Run Code Online (Sandbox Code Playgroud)

然而,这似乎容易出错.由于strip除非/直到使用评论,否则不需要操作,你可以省略strip并且所有内容最初都能正常工作 - 所以你很可能不会总是记得添加strip.稍后,如果有人在设置变量时添加注释,则Makefile将不再按预期工作.

注意:如本问题所示,存在一个密切相关的问题,即使没有注释,尾随空格也会破坏字符串比较.

问题:有没有更简单方法来处理这个问题?

Joh*_*all 5

这不是GNU Make特有的; 更确切地说,make由POSIX定义这样的工作方式:

string1 = [string2]

名为string1的宏被定义为具有string2的值,其中string2被定义为所有字符(如果有)<equals-sign>,直到注释字符(#)或未转义<newline>.<blank>紧接在之前或之后的任何字符<equals-sign>都应被忽略.

这可以解释为允许您使用尾随空格清楚地创建变量的功能:

FOO = stuff  # this macro has two trailing spaces
BAR = something else# and this one has none
Run Code Online (Sandbox Code Playgroud)

虽然通常可能会更清楚地重新组织你使用的地方,$(FOO)而不是依赖它有模糊的空白.

处理这个问题的最好方法可能就是避免它:有一个约定,你不要对变量定义行放置注释(除非偶尔使有意的空白显式).而不是写这个:

A = a # list of apples
B = b # list of bananas
C = c # list of carrots
Run Code Online (Sandbox Code Playgroud)

写这个:

# list of apples
A = a
# list of bananas
B = b
# list of carrots
C = c
Run Code Online (Sandbox Code Playgroud)

这往往是GNU项目中的风格(例如参见本页底部),但我不记得是否在任何地方记录了这一点.

顺便说一句,在检查空格时,您可能希望echo更多地在命令中引用变量:

rule:
   @echo 'RESULT="$(RESULT)"'
Run Code Online (Sandbox Code Playgroud)

在您的echo RESULT=\"$(RESULT)\"版本中,$(RESULT)未引用shell,因此标签和多个空格被误导地显示为单个空格.