GNU makeのevalがリストをスカラーに変換するのはなぜですか?

GNU makeのevalがリストをスカラーに変換するのはなぜですか?

いくつかのmake変数を定義するためにevalを使用しようとしていますが、リストを暗黙的にスカラーに変換するようです。この動作を回避する方法がわからないようです。これは私の現在の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)

関連情報