如何生成Makefile规则

Hua*_*Lei 2 makefile gnu-make

我想通过这个在Makefile中生成规则:

# $(call cc-defs, ccfiles)
define cc-defs
    $1.files = $(patsubst %.cc,%.proto,$1)
    $1: $1.files
endef
$(foreach ccfile,$(ccfiles), $(eval $(call cc-defs, $(ccfile))))
Run Code Online (Sandbox Code Playgroud)

但失败并显示错误消息:

Makefile:19: *** commands commence before first target.  Stop.
Run Code Online (Sandbox Code Playgroud)

相反,我可以这样做:

# $(call cc-defs, ccfiles)
define cc-defs
    $1.files = $(patsubst %.cc,%.proto,$1)
endef

$(foreach ccfile,$(ccfiles), $(eval $(call cc-defs, $(ccfile))))
$(foreach ccfile,$(ccfiles), $(eval $(ccfile):$($(ccfile).files)))
Run Code Online (Sandbox Code Playgroud)

如何使第一种方法有效?

bob*_*ogo 6

你使用的是哪个版本的make?$(eval)只出现在3.80(它只适用于3.81恕我直言).

要调试makefile,您通常必须恢复到printf调试.要查看发生了什么,请替换evalwarning.这显示了您要做的事情:

$ make --warn
Makefile:6: warning: undefined variable `ccfiles'
make: *** No targets.  Stop.
Run Code Online (Sandbox Code Playgroud)

(旁白:--warn-undefined-variables总是很有用.未定义的变量是不整齐的.)

好的,所以我们需要定义$ccfiles.现在我们得到for循环触发:

$ make --warn ccfiles=1.cc
Makefile:6:    1.c.files = 1.cc
               1.cc:  1.c.files
make: *** No targets.  Stop.
Run Code Online (Sandbox Code Playgroud)

精细.您没有给出配方,也没有默认目标.你也错过了一些变量扩展,并在$(for)调用中有一个额外的空间(顽皮!).试试这个:

$ cat Makefile
# $(call cc-defs,ccfiles)
define cc-defs
  $1.files = $(patsubst %.cc,%.proto,$1)
  $1: $$($1.files) ; echo '[$$@]'
endef
$(foreach ccfile,$(ccfiles), $(eval $(call cc-defs,$(ccfile))))

$ make ccfiles=1.cc
make: *** No rule to make target `1.proto', needed by `1.cc'.  Stop.
Run Code Online (Sandbox Code Playgroud)