在定义的函数中使用 awk 命令时无法获得正确的参数

can't get correct arguments when use awk command in a defined function

项目中有一个version.h文件,像这样:

#ifndef _VERSION_H_
#define _VERSION_H_

#define PROJNAME "Uranium"
#define VERSION  "1.0.1"

#endif

而且我想在使用make编译项目时打印项目名称和版本。 所以我添加了以下 makefile:

PROJNAME_KEYWORD = "PROJNAME"
VERSION_KEYWORD  = "VERSION"

define GetPropValue
  $(shell \
    awk '{ \
      split($[=11=], words, " "); \
      for (i in words) { \
        if (index(words[i], $$(1)) != 0) { \
          word = words[i + 1]; \
          gsub("\"", "", word); \
          print word; \
          break; \
        } \
      } \
    }' version.h \
  )
endef

ifndef PROJNAME
  PROJNAME = $(call GetPropValue, $(PROJNAME_KEYWORD))
endif

ifndef VERSION
  VERSION = $(call GetPropValue, $(VERSION_KEYWORD))
endif

预计会有这个:

PROJNAME = Uranium
VERSION = 1.0.1

但实际上我得到了这个,

PROJNAME=_VERSION_H_ _VERSION_H_ PROJNAME VERSION
VERSION=_VERSION_H_ _VERSION_H_ PROJNAME VERSION

经过一些调试过程,我在

中找到了$$(1)
if (index(words[i], $$(1)) != 0) {

行不正确, 当我用 "PROJNAME" 替换 $$(1) 时, 我可以得到正确的结果,

PROJNAME = Uranium

$$(1) 应该是参数,比如 $(PROJNAME_KEYWORD) from

$(call GetPropValue, $(PROJNAME_KEYWORD))

那么在这种情况下,该怎么写呢?

总结

既然要获取记录在C头文件中的宏定义数据,最自然的应用工具就是C预处理器。那么完全跳过 user-defined 函数并使用

怎么样?
PROJNAME = $(shell echo PROJNAME | cat version.h - | cpp -P | tr -d '"')

说明

您已经在使用 GNU 版本的 make,尤其是其 $(shell) 功能。 $(shell) 执行 shell 命令并计算命令标准输出的内容。在这种情况下,执行的命令决定了version.h中定义的预处理器宏的定义

  • version.h 的内容与包含裸宏名称的行连接起来,并且

  • 将结果通过管道输送到预处理器中。预处理器的 -P 选项会抑制额外输出的生成,例如 line-number 指标。

宏定义包含的引号不是您要分配给 make 变量的值的一部分,因此预处理器输出进一步通过管道传输到 tr 中以去除这些引号。

演示

给定这个完整的 makefile ...

PROJNAME = $(shell echo PROJNAME | cat version.h - | cpp -P | tr -d '"')

demo:
    @echo '$(PROJNAME)'

... ,并且问题中出现的 version.h 文件位于同一目录中, 运行 makemake demo 产生此输出:

Uranium

我改天试了,

if (index(words[i], $$(1)) != 0) { \

$$(1)不正确,应替换为$(1),

if (index(words[i], $(1)) != 0) { \

但这会导致另一个问题, 当 makefile 在 运行,

之前进行静态检查时会发生很多错误
awk: line 1: syntax error at or near )
awk: line 1: syntax error at or near }

这意味着静态检查不知道它是 $(1),可能会替换为空,但我不确定, 要解决此问题,请在 $(1) 之前添加 "", 所以应该是这样的,

if (index(words[i], ""$(1)) != 0) { \

静态检查没问题,$(1)会被argv[1]正确替换