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

Comments 变量赋值后的尾随注释颠覆比较,comments,makefile,gnu-make,Comments,Makefile,Gnu Make,在GNU make中,附加到变量赋值的尾随注释会阻止后续通过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=\"$

在GNU make中,附加到变量赋值的尾随注释会阻止后续通过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)\"
这是输出

$ make
RESULT=" a c"
A="a"
B="b "
C="c"
从显示的结果值可以看出,ifeq受赋值B中注释的影响。回显变量B表明问题不在于注释,而在于中间的空间

显而易见的解决方案是在比较之前显式地使用空格,就像这样

ifeq "$(strip $(B))" "b"
  RESULT += b
endif
然而,这似乎容易出错。由于除非/直到使用注释,否则不需要执行条带操作,因此您可以省略条带,并且最初一切都会正常工作-因此您可能不会总是记得添加条带。稍后,如果有人在设置变量时添加注释,则Makefile将不再按预期工作

注意:有一个密切相关的问题,如中所示,即使没有注释,尾随空格也会打断字符串比较


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

这不是GNU所特有的;相反,make是:

string1=[string2]

名为string1的宏被定义为具有string2的值,其中string2被定义为字符串后面的所有字符(如果有),直到注释字符或未转义字符。应忽略字符前后的任何字符

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

FOO = stuff  # this macro has two trailing spaces
BAR = something else# and this one has none
虽然通常情况下,重新组织您使用$FOO的位置比依赖于它有模糊的空格更为清晰

处理这个问题的最好方法可能就是避免它:有一个惯例,除了偶尔使有意的空白显式外,不要在变量定义行上添加注释。而不是写这封信:

A = a # list of apples
B = b # list of bananas
C = c # list of carrots
写下:

# list of apples
A = a
# list of bananas
B = b
# list of carrots
C = c
这往往是GNU项目中的风格,例如,请参阅,尽管我不记得是否在任何地方记录了这一点

顺便提一下,在检查空白时,您可能希望在echo命令中引用更多变量:

rule:
   @echo 'RESULT="$(RESULT)"'

在您的echo RESULT=\$RESULT\version中,$RESULT没有从shell中引用,因此制表符和多个空格被误导地显示为单个空格。

这不是GNU Make的特有功能;相反,make是:

string1=[string2]

名为string1的宏被定义为具有string2的值,其中string2被定义为字符串后面的所有字符(如果有),直到注释字符或未转义字符。应忽略字符前后的任何字符

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

FOO = stuff  # this macro has two trailing spaces
BAR = something else# and this one has none
虽然通常情况下,重新组织您使用$FOO的位置比依赖于它有模糊的空格更为清晰

处理这个问题的最好方法可能就是避免它:有一个惯例,除了偶尔使有意的空白显式外,不要在变量定义行上添加注释。而不是写这封信:

A = a # list of apples
B = b # list of bananas
C = c # list of carrots
写下:

# list of apples
A = a
# list of bananas
B = b
# list of carrots
C = c
这往往是GNU项目中的风格,例如,请参阅,尽管我不记得是否在任何地方记录了这一点

顺便提一下,在检查空白时,您可能希望在echo命令中引用更多变量:

rule:
   @echo 'RESULT="$(RESULT)"'

在echo RESULT=\$RESULT\version中,$RESULT没有从shell中引用,因此选项卡和多个空格被误导地显示为单个空格。

以下是我的一些原始想法:

将strip始终与ifeq一起使用作为一项策略 不使用strip是一个罕见的例外,需要在评论中做出解释。 不要在Makefile中手动设置配置变量 找到或创建一些其他工具来实现这一点。 也许POSIX shell就足够了,尽管我认为shell变量的细微差别可能比make的更糟糕。 我怀疑Autoconf/Automake/etc解决了这个问题,但我的感觉是,这在大多数情况下都是矫枉过正的。 使用某种lint工具来发现此类问题 我不知道有这样的工具存在。 修改GNU make以解决此问题。 最好尽量减少对现有makefile的影响。 修改make语言,以便默认情况下删除尾随空格 使用更现代的构建工具,而不是GNU make
以下是我的一些原始想法:

将strip始终与ifeq一起使用作为一项策略 不使用strip是一个罕见的例外,需要在评论中做出解释。 不要在Makefile中手动设置配置变量 找到或创建一些其他工具来实现这一点。 也许POSIX shell就足够了,尽管我认为shell变量的细微差别可能比make的更糟糕。 我怀疑Autoconf/Automake/etc解决了这个问题,但我的感觉是 这在大多数情况下都是过分的。 使用某种lint工具来发现此类问题 我不知道有这样的工具存在。 修改GNU make以解决此问题。 最好尽量减少对现有makefile的影响。 修改make语言,以便默认情况下删除尾随空格 使用更现代的构建工具,而不是GNU make
丑陋,但也许更简单。将来编辑这篇文章的人可能至少会注意到,你可能是故意让它难看的

A = $(strip a )##
B = $(strip b )## trailing comment
C = $(strip c )##

丑陋,但也许更简单。将来编辑这篇文章的人可能至少会注意到,你可能是故意让它难看的

A = $(strip a )##
B = $(strip b )## trailing comment
C = $(strip c )##

100%清楚地说,问题不在于后面的评论。这是评论前的空白。如果您编写b=b尾随注释,因此注释字符前没有尾随空格,尽管它看起来很难看,但效果很好。而且,除了不添加尾随空间之外,没有简单的方法来处理它。大多数体面的编辑器都有一种模式,可以检测并突出显示尾随空格,甚至在保存时自动删除。用那个。我不会试图为make设计师做出的奇怪决定辩护,只是想说,那是很久以前的事了。顺便说一句,这里有一个有趣的线索,OP有着完全相同的问题,但提出了一个不同的问题:@madscitect:我同意你的建议,使用一个突出尾随空格的编辑器。但仅仅因为我用了一个,并不意味着其他人都会用。我希望我的makefile能够以合理的方式工作,即使对于那些不知道所有技巧和陷阱的人来说也是如此。这是评论前的空白。如果您编写b=b尾随注释,因此注释字符前没有尾随空格,尽管它看起来很难看,但效果很好。而且,除了不添加尾随空间之外,没有简单的方法来处理它。大多数体面的编辑器都有一种模式,可以检测并突出显示尾随空格,甚至在保存时自动删除。用那个。我不会试图为make设计师做出的奇怪决定辩护,只是想说,那是很久以前的事了。顺便说一句,这里有一个有趣的线索,OP有着完全相同的问题,但提出了一个不同的问题:@madscitect:我同意你的建议,使用一个突出尾随空格的编辑器。但仅仅因为我用了一个,并不意味着其他人都会用。我希望我的makefile能够以一种合理的方式工作,即使对于那些不知道所有技巧和陷阱的人来说也是如此。谢谢你的好见解。不过,我要说,我不喜欢你提出的公约,原因有两个:1.我认为它更难编辑,也更难阅读。2与所有Makefiles的所有未来用户通信是一个非直观的要求,这将是一个问题。另外,感谢您关于报价的说明。我想我永远都不会完全理解POSIX shell是如何操纵字符串的。我想make和shell都有古怪的字符串管理的共同特点——在这两种情况下都是基于很久以前做出的决定。谢谢你的好见解。不过,我要说,我不喜欢你提出的公约,原因有两个:1.我认为它更难编辑,也更难阅读。2与所有Makefiles的所有未来用户通信是一个非直观的要求,这将是一个问题。另外,感谢您关于报价的说明。我想我永远都不会完全理解POSIX shell是如何操纵字符串的。我猜make和shell都有奇怪的字符串管理的共同特点——在这两种情况下都是基于很久以前做出的决定。使用strip无法扩展。此外,ifeq并不是唯一一个尾随空格出现问题的情况。使用strip不会缩放。此外,ifeq并不是尾随空间成为问题的唯一情况。