이 간단한 레시피가 왜 효과가 없을까요?
.PHONY: test
test:
foo := $(shell ls | grep makefile) ;\
echo $(foo)
밝혀지다
$> make test
makefile:65: warning: undefined variable 'foo'
foo := makefile ;\
echo
/bin/sh: 1: foo: not found
그럼 제가 아는 바로는 변수 foo
에 값이 설정되어 있는데 makefile
사용할 수 없다는 건가요? 그러나 동일한 쉘에서 실행되는 단일 행 명령입니까?
그러나 이것은 작동합니다
@$(eval export foo := $(shell ls | grep makefile)) \
echo $(foo)
echo
그렇다면 우리가 시도할 때 할당이 아직 평가되지 않았기 때문에 첫 번째 예의 변수에 액세스할 수 없는 것 같습니다.
더 자세히 살펴보면 어떻게 이 작업을 수행할 수 있나요?
.PHONY: test
test:
@$(eval export files = $(shell ls))
for f in $(files) ; do \
t = $(ls | grep $$f) ; \
echo $$t;\
done
답변1
나는 당신의 루프를 보았습니다... 인용문은 다음과 같습니다:
.PHONY: test
test:
@$(eval export files = $(shell ls))
for f in $(files) ; do \
t = $(ls | grep $$f) ; \
echo $$t;\
done
그럼... $(eval ... )
make에서 명령을 실행해 보세요.
$(shell ls)
ls
셸에서 명령을 실행하고 출력을 바꿉니다.
따라서 실행되는 명령은 $(eval ... )
다음과 같습니다 export files = file file2 makefile source.c
. 이 명령은 files라는 이름의 make 변수를 생성하고 이를 submake로 내보냅니다. 따라서 내보내기가 필요하지 않을 수도 있습니다.
전체를 $(eval ... )
대체하여 사용할 수 있으며 규칙 외부에 배치 files = $(wildcard *)
할 수 있습니다 .:=
이 for
루프(4줄)는 셸에서 실행됩니다. 가장 먼저 할 일은 make 변수와 함수를 바꾸는 것입니다. 이상한 점은 $(ls | grep $$f)
. ls는 make 함수가 아니기 때문에 정의되지 않은 변수를 확장하려고 시도합니다. 이는 빈 문자열입니다. 이것이 쉘 $(...)
연산자라면 $를 두 배로 늘려야 합니다. eval을 기반으로 .Extended $$
로 확장됩니다 .$
$(files)
이것은 다음과 같습니다(이전 예를 사용하면).
for f in file file2 makefile source.c ; do
t =
echo $t;
done
언뜻 보기에 이것은 네 개의 빈 줄을 에코하는 것처럼 보일 수 있지만 사실은 아닙니다. 이 명령은 t =
실제로 프로그램을 실행 t
하고 등호를 인수로 전달합니다. t
아마도 존재하지 않을 것입니다. 따라서 t가 유효한 프로그램이 아니라는 것을 나타내는 4개의 오류가 발생합니다. 각 오류 뒤에는 빈 줄이 옵니다(t가 다른 곳에서 정의되지 않은 경우).
당신이 원하는 것에 더 가까운 것은 다음과 같습니다:
files := $(wildcard *)
.PHONY: test
test:
for f in $(files) ; do \
t=$$(ls | grep $$f) ; \
echo $$t ; \
done
그러면 다음이 출력됩니다.
file file2
file2
makefile
source.c
첫 번째 줄에는 이름에 "file"이 포함되어 있으므로 두 개의 파일이 나열됩니다. 이것이 원하는 것이 아니라면 다음을 고려해 볼 수 있습니다.
files := $(wildcard *)
.PHONY: test
test:
for f in $(files) ; do \
echo $$f ; \
done
또는 (GNU에만 해당될 수도 있음):
files := $(wildcard *)
.PHONY: test
test:
$(foreach f, $(files), echo $f ; )
답변2
make target 레시피 내에서 명령은 레시피 외부의 로직과 다르게 처리됩니다(셸 생성).
레시피 외부로 변수를 이동할 수 있습니다.
.PHONY: test
foo := $(shell ls | grep makefile)
test:
echo $(foo)
아니면 정중하게이 문제, 평가 사용:
.PHONY: test
test:
$(eval foo=$(shell ls | grep makefile))
echo $(foo)
둘 다 다음을 출력합니다.
echo makefile
makefile