这是GNU make的`filter`中的错误吗?

问题描述 投票:2回答:2

我有一个像这样开始的Makefile:

CORE_PATH:=$(filter %/makefile_ltlibs.inc,$(MAKEFILE_LIST))

foobar:
        @echo "MAKEFILE_LIST = \"$(MAKEFILE_LIST)\""
        @echo "filter = \"$(filter %/makefile_ltlibs.inc,$(MAKEFILE_LIST))\""
        @echo "CORE_PATH = \"$(CORE_PATH)\""

当我运行gmake foobar时,得到以下输出:

MAKEFILE_LIST = " GNUmakefile ../../matrixssl.test/crypto/Makefile ../common.mk ../core/makefiles/detect-and-rules.mk ../../matrixssl.test/crypto/makefile.inc makefile ../../matrixssl.test/crypto/makefile_ltlibs.inc"
filter = "../../matrixssl.test/crypto/makefile_ltlibs.inc"
CORE_PATH = ""

[CORE_PATH在这里怎么可能为空?!

编辑:

我把它做成一个独立的测试用例:

FILTER_LIST1 := " foo bar"
FILTER_LIST2 := " foo bar "

WORD11 := $(filter foo,$(FILTER_LIST1))
WORD12 := $(filter bar,$(FILTER_LIST1))

WORD13 := $(filter foo,"$(FILTER_LIST1) ")
WORD14 := $(filter bar,"$(FILTER_LIST1) ")

WORD21 := $(filter bar,$(FILTER_LIST2))

foobar:
        @echo "FILTER_LIST1 = \"$(FILTER_LIST1)\""
        @echo "FILTER_LIST2 = \"$(FILTER_LIST2)\""
        @echo "WORD11 = \"$(WORD11)\""
        @echo "WORD12 = \"$(WORD12)\""
        @echo "WORD13 = \"$(WORD13)\""
        @echo "WORD14 = \"$(WORD14)\""
        @echo "WORD21 = \"$(WORD21)\""

输出

FILTER_LIST1 = " foo bar"
FILTER_LIST2 = " foo bar "
WORD11 = "foo"
WORD12 = ""
WORD13 = "foo"
WORD14 = ""
WORD21 = "bar"

我的结论是,最后一个条目的filter被打断了。还是我做错了?

makefile gnu-make
2个回答
3
投票

make是与字符串分隔符无关的-像" ' \等字符不代表要做什么。因此,bar"实际上是以"结尾的4个字符的字符串,并且在filter操作中将与搜索字符串bar不匹配。

与原始字符串相同:尝试对space分隔的字符串列表%/makefile_ltlibs.inc中的" GNUmakefile ../../matrixssl.test/crypto/Makefile ../common.mk ../core/makefiles/detect-and-rules.mk ../../matrixssl.test/crypto/makefile.inc makefile ../../matrixssl.test/crypto/makefile_ltlibs.inc"进行模式匹配不会出现匹配,因为最后的"破坏了对模式的一致性。

如果您要进行大量的字符串和列表处理,可能会像gmtt这样的GNUmake帮助器库很方便。


0
投票

MAKEFILE_LIST的问题来自于这样的事实,即每次make处理include指令时,此变量都会扩展。现在,使用:=设置CORE_PATH的值将告诉make立即评估表达式。由于您位于Makefile的开头,因此MAKEFILE_LIST仅包含Makefile(请参见description of the variable中给出的示例),并且过滤器返回空值。

另一方面,一旦完全解析了Makefile,便会评估配方。因此,在MAKEFILE_LIST中有更长的序列,可以对其进行过滤。要使用CORE_PATH获得相同的内容,请使用CORE_PATH = ...进行定义。然后,仅在使用CORE_PATH时才扩展定义,而在定义时不扩展(有关变量的这两个“风味”的更多信息,请参见GNU Make manual)。

关于编辑,正如Vroomfondel所提到的,FILTER_LIST1由3个词组成(您可以通过执行$(words $(FILTER_LIST1))"foobar"来看到它们,但都不是bar。类似地,FILTER_LIST2有4个单词,"foobar",并且可以在列表中找到bar

© www.soinside.com 2019 - 2024. All rights reserved.