![GNU make의 eval이 목록을 스칼라로 변환하는 이유는 무엇입니까?](https://linux55.com/image/124261/GNU%20make%EC%9D%98%20eval%EC%9D%B4%20%EB%AA%A9%EB%A1%9D%EC%9D%84%20%EC%8A%A4%EC%B9%BC%EB%9D%BC%EB%A1%9C%20%EB%B3%80%ED%99%98%ED%95%98%EB%8A%94%20%EC%9D%B4%EC%9C%A0%EB%8A%94%20%EB%AC%B4%EC%97%87%EC%9E%85%EB%8B%88%EA%B9%8C%3F.png)
일부 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)