我试图使用 eval 来定义一些 make 变量,但它似乎隐式地将列表转换为标量。我似乎不知道如何避免这种行为。这是我当前的 Makefile:
foo_man_srcs := a.c b.c
define GEN_OBJS =
$(1)_srcs := a.c b.c
$(1)_gen_objs := $(addprefix objdir/,$$($(1)_srcs:.c=.o))
$(1)_man_objs := $(addprefix objdir/,$(foo_man_srcs:.c=.o))
endef
$(eval $(call GEN_OBJS,foo))
all:
echo "foo_gen_objs: $(foo_gen_objs)"
echo "foo_man_objs: $(foo_man_objs)"
这是我观察到的当前行为:
$ make
echo "foo_gen_objs: objdir/a.o b.o"
foo_gen_objs: objdir/a.o b.o
echo "foo_man_objs: objdir/a.o objdir/b.o"
foo_man_objs: objdir/a.o objdir/b.o
我的期望是 $(foo_gen_objs) 和 $(foo_man_objs) 都会计算出相同的值,但 eval 似乎将 $$($(1)_srcs) 视为标量而不是列表。我怎样才能解决这个问题?
答案1
解决方案非常简单:您应该转义 addprefix() 函数的 $ 符号:
define GEN_OBJS =
$(1)_srcs := a.c b.c
$(1)_gen_objs := $$(addprefix objdir/,$$($(1)_srcs:.c=.o))
$(1)_man_objs := $$(addprefix objdir/,$(foo_man_srcs:.c=.o))
endef
但更重要的是了解如何自己调试此类问题。基本上,您只需将“eval”替换为“info”,make 将打印 eval 的输入而不是解析它。
在您的示例中,将“eval”替换为“info”,然后调用 make 会产生:
foo_srcs := a.c b.c
foo_gen_objs := objdir/$(foo_srcs:.c=.o)
foo_man_objs := objdir/a.o objdir/b.o
正如您所看到的,call() 在调用 eval() 之前扩展了 addprefix() 函数。如果你按照我上面写的那样修复你的 makefile,你将得到:
foo_srcs := a.c b.c
foo_gen_objs := $(addprefix objdir/,$(foo_srcs:.c=.o))
foo_man_objs := $(addprefix objdir/,a.o b.o)