"Makefile:6: ***Multiple target mode. Stopped."로 make가 중지되는 이유는 무엇입니까?

"Makefile:6: ***Multiple target mode. Stopped."로 make가 중지되는 이유는 무엇입니까?

표적마크다운 파일로 슬라이드쇼를 작성한 다음 표시용으로 컴파일하고 웹 서버에 업로드하는 등의 작업을 수행합니다. makefile에 마크다운을 작성한 후 단계를 구성하고 싶습니다.

PROJNAME = `pwd | grep -oP '(\w|-)+' | tail -n 2 | head -n 1 | tr '[:upper:]' '[:lower:]'`

presentation: slides.pandoc
    pandoc --self-contained --data-dir=$(HOME)/.pandoc --template=slides/revealjs_niels_tmpl.html -V revealjs-url:$(HOME)/.pandoc/revealjs -V theme:solarized slides.pandoc -f markdown -t revealjs -o $(PROJNAME).html

onlinepresent: $(PROJNAME).html
    cp $(PROJNAME).html $(HOME)/Share/index.html

설명하다 PROJNAME프로젝트 폴더 이름을 찾아 소문자로 변환하세요. 이것을 사용하고 제목에 표시된 메시지를 생성하는 예제 폴더에서 결과는 입니다 ws-anno-ii. presentation규칙은 슬라이드쇼를 html로 컴파일하는 데 사용됩니다 pandoc. 매크로는 PROJNAME출력 파일의 이름을 정의하는 데 사용됩니다. 마운트된 외부 파일 시스템( )에 파일이 있는 경우 프로젝트 이름( )이 포함된 파일을 중지 onlinepresent위치 에 복사해야 합니다 make. 존재하지 않는 경우에는 물론 규칙을 먼저 적용해야 합니다. 하지만 명령을 입력하면 아무 일도 일어나지 않고 메시지가 나타납니다.ws-anno-ii.htmlSharepresentationmake

프로세스 make가 중지되고 Makefile:6: *** multiple target patterns. Stop.라인을 참조합니다.onlinepresent: $(PROJNAME).html

왜 이런 일이 발생하는지 설명해 줄 수 있는 사람이 있나요?

답변1

make 변수의 값은 PROJNAME다음과 같습니다.

`pwd | grep -oP '(\w|-)+' | tail -n 2 | head -n 1 | tr '[:upper:]' '[:lower:]'`

백틱 문자는 make에서 특별하지 않습니다. 쉘 명령에서 이 변수를 사용하면 쉘은 역따옴표를 보고 이를 명령 대체로 해석합니다. 그러나 make가 해석하는 변수를 사용하면 백틱은 특별한 작업을 수행하지 않습니다. onlinepresent: $(PROJNAME).html변수가 확장되면 행은 다음과 같습니다.

onlinepresent: `pwd | grep -oP '(\w|-)+' | tail -n 2 | head -n 1 | tr '[:upper:]' '[:lower:]'`.html

onlinepresent구문 분석을 , 콜론, `pwd, \, grep, -oP, , , , , , '(\w|-)+', , , , , 콜론, , 콜론, , , 콜론, , 콜론, 으로 둡니다 . 가장 오른쪽 콜론 왼쪽에 여러 단어가 있으므로 "다중 대상 패턴"입니다.|tail-n2|head-n1|tr'[upper]''[lower]'`.html

make가 읽을 수 있는 위치에서 쉘 명령의 출력을 사용하려면 다음을 호출해야 합니다.shell기능. 이는 GNU make 기능이며 다른 make 구현에는 영향을 미치지 않습니다.

PROJNAME = $(shell pwd | grep -oP '(\w|-)+' | tail -n 2 | head -n 1 | tr '[:upper:]' '[:lower:]'`)

이렇게 하면 PROJNAME변수가 소문자로 변환된 작업 디렉터리의 마지막에서 두 번째 구성 요소로 설정됩니다.

현재 디렉터리를 사용하는 것은 취약하다는 점에 유의하십시오. 즉, 다른 디렉터리에서 대상으로 호출하면 makefile이 작동하지 않는다는 의미입니다. PROJNAME대상까지의 경로에서 계산하는 것이 더 강력합니다. 소문자 부분이 아닌 경우 make 함수를 사용하여 완전히 수행할 수 있습니다(문제가 있는 경우). (코드 분할의 목적은 실제로 경로 이름 구성 요소를 추출하는 것이라고 가정합니다.)

$(notdir $(patsubst %/,%,$(dir $(patsubst %/,%,$(dir $(abspath $@))))))

그러나 GNU make에는 대소문자 변환 도구가 없습니다. 어쨌든 쉘을 호출하는 경우 더 간단하게 만들 수 있습니다.

PROJNAME = $(shell set -x; echo '$(abspath $@)' | awk -F/ '{$$0=tolower($$0); print $$(NF-2)}')
onlinepresent: $(PROJNAME).html
        cp $< $$HOME/Share/index.html

$$makefile에서의 사용에 유의하십시오. 이는 $쉘 명령의 내용이 됩니다. 이는 변수가 정의될 ​​때가 아니라 사용할 때마다 평가되기 때문에 작동합니다 PROJNAME(make의 변수 정의는 사용된 경우 각 사용마다 확장되고 =사용된 경우 읽기 할당 시 확장됩니다 :=).

답변2

달리고 make onlinepresent, make목표를 향해 걷고 onlinepresent, 무엇이 필요한지 확인하는 $(PROJNAME).html것은 일종의잘못된...make의 관점에서 보면 직접 제공되는 대상이 없기 때문입니다 $(PROJNAME).html.

나는 또한 귀하의 할당 PROJNAME가능성결과.

사용해 보세요

presentation: slides.pandoc
#your pandoc rule
onlinepresent: presentation
#your mv command

이는 make목표를 달성하기 위해서는 onlinepresent목표가 필요하다는 것을 보여줍니다. presentation그런 다음 대상 표현은 make에게 이것이 필요하다는 것을 알려주므로 새 규칙이거나 수정된 slides.pandoc​​규칙인 경우 해당 규칙을 실행합니다.slides.pandoc

또는

다음과 같이 presentation대상 이름을 바꿀 수도 있습니다.$(PROJNAME).html

$(PROJNAME).html: slides.pandoc
#your pandoc rule
onlinepresent: $(PROJNAME).html
#your mv command

관련 정보