在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所示,存在一个密切相关的问题,即使没有注释,尾随空格也会破坏字符串比较。
问题:是否有更强的傻瓜式方式来处理此问题?
答案 0 :(得分:5)
这不是GNU Make特有的;相反,make
是defined by POSIX to work this way:
string1 = [string2]
名为 string1 的宏被定义为具有 string2 的值,其中 string2 被定义为所有字符,如果有的话,在
<equals-sign>
,最多为评论字符(#
)或未转义的<newline>
。 <{1}}之前或之后的任何<blank>
个字符都将被忽略。
这可以解释为一个允许您使用尾随空格清晰创建变量的功能:
<equals-sign>
虽然通常可能会更清楚地重新组织你使用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
这往往是GNU项目中的风格(例如参见the bottom of this page),但我不记得是否记录在任何地方。
顺便说一句,在检查空格时,您可能希望在# list of apples
A = a
# list of bananas
B = b
# list of carrots
C = c
命令中引用变量:
echo
在rule:
@echo 'RESULT="$(RESULT)"'
版本中,echo RESULT=\"$(RESULT)\"
未引用shell,因此标签和多个空格被误导性地显示为单个空格。
答案 1 :(得分:0)
以下是我的一些原创想法:
strip
ifeq
strip
将是一个罕见的例外,需要在评论中进行解释。答案 2 :(得分:0)
丑陋,但也许更加万无一失。任何在将来编辑此内容的人都可能至少会注意到你或许会故意让它变得丑陋。
A = $(strip a )##
B = $(strip b )## trailing comment
C = $(strip c )##