Makefile findstring 不会匹配数字字符
Makefile findstring won't match numerical character
CLANG_MAJOR_VER = x`${CXX} --version | egrep -i 'clang' | awk '{print $}' | awk '{ gsub(/\./, " "); print $ }'`xx
PAT = x6
CLANG_NAME = `${CXX} --version | grep -i 'clang' | awk '{print $}'`
CLANG_DEF = $(if $(findstring $(PAT),$(CLANG_MAJOR_VER)),abc,def)
all:
@echo $(CLANG_MAJOR_VER)
@echo $(CLANG_NAME)
@echo $(CLANG_DEF)
结果:
x6xx
clang
如果 PAT 是 x 或 xx,则 $(CLANG_DEF) 将是 abc,如果 PAT = 6, x6, 6x 那么 $(CLANG_DEF) 将是 def.
a library 可以剖析简单的(glob)字符串表达式:
include gmtt/gmtt.mk
define clang--version =
clang version 3.18.240-2ubuntu4 (tags/RELEASE_380/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
endef
parsed-string = $(call glob-match,$(clang--version),clang version *.*.*-* *Target: *Thread model: *InstalledDir: *)
$(info $(parsed-string))
$(info Major: $(word 2,$(parsed-string)) Minor: $(word 4,$(parsed-string)) Bugfix: $(word 6,$(parsed-string)))
输出:
clang§version§ 3 . 18 . 240 - 2ubuntu4 § (tags/RELEASE_380/final) Target:§ x86_64-pc-linux-gnu Thread§model:§ posix InstalledDir:§ /usr/bin
Major: 3 Minor: 18 Bugfix: 240
您可以在 shell 脚本中使用反引号,但不能在 Makefile 中使用。递归赋值 (VAR = VALUE
) 将确切的右侧字符串分配给您的变量,并在需要时递归地扩展它们,只有在那时,也就是说,在您的情况下,当 make 扩展您的 all
规则,就在将它传递给 shell 之前。所以,如果 PAT = x6
,当 CLANG_DEF
展开时,你有(在连续的步骤中分解):
@echo $(CLANG_DEF)
@echo $(if $(findstring $(PAT),$(CLANG_MAJOR_VER)),abc,def)
@echo $(if $(findstring x6,x`${CXX} --version | egrep -i 'clang' | awk '{print $}' | awk '{ gsub(/\./, " "); print $ }'`xx),abc,def)
@echo $(if $(findstring x6,x`clang --version | egrep -i 'clang' | awk '{print }' | awk '{ gsub(/\./, " "); print }'`xx),abc,def)
@echo $(if ,abc,def)
@echo def
这并不取决于 shell 的评估结果:
clang --version | egrep -i 'clang' | awk '{print }' | awk '{ gsub(/\./, " "); print }'
因为它不是被shell求值的,所以在扩展$(findstring...)
...[=32时它只被make认为是一个字符串=]
但是如果PAT = x
,递归展开就变成:
@echo $(CLANG_DEF)
@echo $(if $(findstring $(PAT),$(CLANG_MAJOR_VER)),abc,def)
@echo $(if $(findstring x,x`${CXX} --version | egrep -i 'clang' | awk '{print $}' | awk '{ gsub(/\./, " "); print $ }'`xx),abc,def)
@echo $(if $(findstring x,x`clang --version | egrep -i 'clang' | awk '{print }' | awk '{ gsub(/\./, " "); print }'`xx),abc,def)
@echo $(if x,abc,def)
@echo abc
您可以尝试使用 $(shell...)
make 函数来代替这种不寻常的 backsticks 用法:
CLANG_MAJOR_VER = x$(shell ${CXX} --version | egrep -i 'clang' | awk '{print $}' | awk '{ gsub(/\./, " "); print $ }')xx
PAT = x6
CLANG_NAME = $(shell ${CXX} --version | grep -i 'clang' | awk '{print $}')
CLANG_DEF = $(if $(findstring $(PAT),$(CLANG_MAJOR_VER)),abc,def)
all:
@echo $(CLANG_MAJOR_VER)
@echo $(CLANG_NAME)
@echo $(CLANG_DEF)
而且,顺便说一下,您检索主版本号的方法不是很可靠(事实上,它在我的 Mac OS 上失败了)。类似于:
clang --version | sed -n '/version/s/.*version \([0-9]\+\).*//p'
可能会好一点(不确定 %100,仅在两个 OSes 和两个 clang 版本上测试)。
CLANG_MAJOR_VER = x`${CXX} --version | egrep -i 'clang' | awk '{print $}' | awk '{ gsub(/\./, " "); print $ }'`xx
PAT = x6
CLANG_NAME = `${CXX} --version | grep -i 'clang' | awk '{print $}'`
CLANG_DEF = $(if $(findstring $(PAT),$(CLANG_MAJOR_VER)),abc,def)
all:
@echo $(CLANG_MAJOR_VER)
@echo $(CLANG_NAME)
@echo $(CLANG_DEF)
结果:
x6xx
clang
如果 PAT 是 x 或 xx,则 $(CLANG_DEF) 将是 abc,如果 PAT = 6, x6, 6x 那么 $(CLANG_DEF) 将是 def.
a library 可以剖析简单的(glob)字符串表达式:
include gmtt/gmtt.mk
define clang--version =
clang version 3.18.240-2ubuntu4 (tags/RELEASE_380/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
endef
parsed-string = $(call glob-match,$(clang--version),clang version *.*.*-* *Target: *Thread model: *InstalledDir: *)
$(info $(parsed-string))
$(info Major: $(word 2,$(parsed-string)) Minor: $(word 4,$(parsed-string)) Bugfix: $(word 6,$(parsed-string)))
输出:
clang§version§ 3 . 18 . 240 - 2ubuntu4 § (tags/RELEASE_380/final) Target:§ x86_64-pc-linux-gnu Thread§model:§ posix InstalledDir:§ /usr/bin
Major: 3 Minor: 18 Bugfix: 240
您可以在 shell 脚本中使用反引号,但不能在 Makefile 中使用。递归赋值 (VAR = VALUE
) 将确切的右侧字符串分配给您的变量,并在需要时递归地扩展它们,只有在那时,也就是说,在您的情况下,当 make 扩展您的 all
规则,就在将它传递给 shell 之前。所以,如果 PAT = x6
,当 CLANG_DEF
展开时,你有(在连续的步骤中分解):
@echo $(CLANG_DEF)
@echo $(if $(findstring $(PAT),$(CLANG_MAJOR_VER)),abc,def)
@echo $(if $(findstring x6,x`${CXX} --version | egrep -i 'clang' | awk '{print $}' | awk '{ gsub(/\./, " "); print $ }'`xx),abc,def)
@echo $(if $(findstring x6,x`clang --version | egrep -i 'clang' | awk '{print }' | awk '{ gsub(/\./, " "); print }'`xx),abc,def)
@echo $(if ,abc,def)
@echo def
这并不取决于 shell 的评估结果:
clang --version | egrep -i 'clang' | awk '{print }' | awk '{ gsub(/\./, " "); print }'
因为它不是被shell求值的,所以在扩展$(findstring...)
...[=32时它只被make认为是一个字符串=]
但是如果PAT = x
,递归展开就变成:
@echo $(CLANG_DEF)
@echo $(if $(findstring $(PAT),$(CLANG_MAJOR_VER)),abc,def)
@echo $(if $(findstring x,x`${CXX} --version | egrep -i 'clang' | awk '{print $}' | awk '{ gsub(/\./, " "); print $ }'`xx),abc,def)
@echo $(if $(findstring x,x`clang --version | egrep -i 'clang' | awk '{print }' | awk '{ gsub(/\./, " "); print }'`xx),abc,def)
@echo $(if x,abc,def)
@echo abc
您可以尝试使用 $(shell...)
make 函数来代替这种不寻常的 backsticks 用法:
CLANG_MAJOR_VER = x$(shell ${CXX} --version | egrep -i 'clang' | awk '{print $}' | awk '{ gsub(/\./, " "); print $ }')xx
PAT = x6
CLANG_NAME = $(shell ${CXX} --version | grep -i 'clang' | awk '{print $}')
CLANG_DEF = $(if $(findstring $(PAT),$(CLANG_MAJOR_VER)),abc,def)
all:
@echo $(CLANG_MAJOR_VER)
@echo $(CLANG_NAME)
@echo $(CLANG_DEF)
而且,顺便说一下,您检索主版本号的方法不是很可靠(事实上,它在我的 Mac OS 上失败了)。类似于:
clang --version | sed -n '/version/s/.*version \([0-9]\+\).*//p'
可能会好一点(不确定 %100,仅在两个 OSes 和两个 clang 版本上测试)。