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 展开时,你有(在连续的步骤中分解):

  1. @echo $(CLANG_DEF)
  2. @echo $(if $(findstring $(PAT),$(CLANG_MAJOR_VER)),abc,def)
  3. @echo $(if $(findstring x6,x`${CXX} --version | egrep -i 'clang' | awk '{print $}' | awk '{ gsub(/\./, " "); print $ }'`xx),abc,def)
  4. @echo $(if $(findstring x6,x`clang --version | egrep -i 'clang' | awk '{print }' | awk '{ gsub(/\./, " "); print }'`xx),abc,def)
  5. @echo $(if ,abc,def)
  6. @echo def

这并不取决于 shell 的评估结果:

clang --version | egrep -i 'clang' | awk '{print }' | awk '{ gsub(/\./, " "); print  }'

因为它不是被shell求值的,所以在扩展$(findstring...)...[=32时它只被make认为是一个字符串=]

但是如果PAT = x,递归展开就变成:

  1. @echo $(CLANG_DEF)
  2. @echo $(if $(findstring $(PAT),$(CLANG_MAJOR_VER)),abc,def)
  3. @echo $(if $(findstring x,x`${CXX} --version | egrep -i 'clang' | awk '{print $}' | awk '{ gsub(/\./, " "); print $ }'`xx),abc,def)
  4. @echo $(if $(findstring x,x`clang --version | egrep -i 'clang' | awk '{print }' | awk '{ gsub(/\./, " "); print }'`xx),abc,def)
  5. @echo $(if x,abc,def)
  6. @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 版本上测试)。