如何生成Makefile规则

时间:2011-03-09 08:25:48

标签: 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))))

但失败并显示错误消息:

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)))

如何使第一种方法有效?

2 个答案:

答案 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.