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)

관련 정보