2012-03-31 26 views
0

在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" 

正如你可以从RESULT显示值看出,ifeq是受的存在在B的转让中发表评论。回显变量B,表明的问题不是评论,而是介入空间

显而易见的解决方案是明确strip空白像这样比较之前...

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

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

注意:如this question所示,存在一个密切相关的问题,即使没有评论,尾随空格可能会断开字符串比较。

问:有没有更多的傻瓜方式来解决这个问题?

+2

只是100%清楚,它不是尾随的评论是问题。这是评论前的空白。如果你写了'b = b#尾注释',所以在注释字符之前没有尾部空格,虽然它看起来很丑,但它工作正常。而且,除了不添加尾部空格以外,没有万无一失的方法来处理它。大多数体面的编辑器都会有一种检测并突出显示尾随空白的模式,或者甚至在保存时自动将其删除。使用它。我不会试图捍卫让设计师做出的奇怪的决定,只是说很久以前。 – MadScientist 2012-03-31 15:11:12

+0

顺便说一下,这里是一个有趣的线程,OP有完全相同的问题(但要求一个不同的问题):http://old.nabble.com/White-Space-Problems--Again-td22756435.html – nobar 2012-03-31 16:49:22

+0

@ MadScientist:我同意你的建议,使用一个突出尾部空格的编辑器。但仅仅因为我使用了一个,并不意味着其他人都会这样做。即使对于不了解所有技巧和陷阱的人,我也希望我的Makefiles能够以合理的方式工作。 – nobar 2012-03-31 21:36:13

回答

5

这不是GNU Make特有的东西;相反,makedefined by POSIX to work this way

string1 = [string2]

命名字符串1定义宏为具有<equals-sign>后的字符串2,其中字符串2被定义为所有字符,如果有的话,该值,注释字符(#)或未转义的<newline><equals-sign>之前或之后的任何<blank>字符都应被忽略。

这可以被理解为一个功能,让您清楚地创建具有尾随空格变量:

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项目的样式(见例如the bottom of this page),但我不记得这是否记录任何地方。

顺便说一下,检查空格时,你可能要引用您的变量在echo命令的更多:

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

在你echo RESULT=\"$(RESULT)\"版本,$(RESULT)不是从壳报价,所以制表符和多个空格都被误导显示为单个空格。

+0

谢谢你的好的见解。我会说,我不喜欢你提出的约定,原因有两个:1)编辑起来更麻烦,而且更难读(在我看来)。 2)这是一个非直观的要求,将会传递给所有未来的所有Makefiles用户。 – nobar 2012-03-31 17:00:19

+0

另外,感谢关​​于报价的说明。我不认为我会完全理解POSIX shell如何操纵字符串。我猜'make'和'shell'具有古怪字符串管理的共同特点 - 两种情况都是基于很久以前做出的决定。 – nobar 2012-03-31 17:04:55

0

这里是我有一些原始的想法:

  • 使它成为一个政策总是使用stripifeq
    • 不使用strip将是一个罕见的例外,并且需要在一个解释注释。
  • 一个Makefile
    • 找到或创造一些其他的工具来做到这一点的里面不要手动设置配置变量。
    • 也许POSIX shell就足够了(尽管我认为shell变量的细微差别可能比make的差异更大)。
    • 我怀疑GNU build system(Autoconf/Automake /等)解决了这个问题,但我的感觉是这对于大多数目的来说是过分的。
  • 使用某种“皮棉”工具来找到这些类型的问题
    • 我不知道有任何这样的工具的存在。
  • 修改GNU make来解决这个问题。
    • 优选最小化对现有Makefiles的影响。
    • 修改make语言,使默认拖尾空间被剥离
  • 使用更现代化的构建工具,而不是GNU使
+0

使用'strip'不会缩放。此外,ifeq并不是尾随空格可能成为问题的唯一情况。 – nobar 2017-08-10 21:49:46

0

丑,但也许更万无一失。任何在将来编辑它的人可能至少会注意到,你可能故意使它变得丑陋。

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