我想在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))))
但失败并显示错误消息:
Makefile:19: *** commands commence before first target. Stop.
相反,我可以通过以下方式实现:
# $(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)))
如何使第一种方法有效?
答案 0 :(得分:6)
您使用的是哪个版本的品牌? $(eval)
仅出现在3.80(并且它仅适用于3.81恕我直言)。
要调试makefile,您通常必须恢复到 printf debugging 。要查看正在进行的操作,请将eval
替换为warning
。这表明你要做的是:
$ make --warn
Makefile:6: warning: undefined variable `ccfiles'
make: *** No targets. Stop.
(旁白:--warn-undefined-variables
总是很有用。未定义的变量是不整齐的。)
O.K。,所以我们需要定义$ccfiles
。现在我们得到for循环触发:
$ make --warn ccfiles=1.cc
Makefile:6: 1.c.files = 1.cc
1.cc: 1.c.files
make: *** No targets. Stop.
精细。您没有给出配方,也没有默认目标。你也错过了一些变量扩展,并在$(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.
答案 1 :(得分:1)
请注意,如果您要做的只是变量中的所有文件都依赖于(或来自).proto文件,那么您就不需要$(eval)。
模式规则可以(并且也可以在旧版本的GNU Make中使用):
$(ccfiles): %.cc: %.proto
echo '[$@]'
当ccfiles变量包含任何未命名为* .cc的条目时,这会产生抱怨的副作用(尽管在这种情况下它仍会执行规则)。
$ make ccfiles=hello.cc
make: *** No rule to make target `hello.proto', needed by `hello.cc'. Stop.
$ touch hello.proto
$ make ccfiles=hello.cc
[hello.cc]
$ make ccfiles=hello.c
Makefile:1: target `hello.c' doesn't match the target pattern
[hello.c]
如果变量可以包含很多内容,但您只想将此处理添加到.cc文件中,只需添加一个过滤器:
$(filter %.cc,$(ccfiles)): %.cc: %.proto
echo '[$@]'
然后导致:
$ make ccfiles=hello.cc
[hello.cc]
$ make ccfiles=hello.c
make: *** No targets. Stop.