답변:
기본적으로 Makefile 대상은 "파일 대상"이며 다른 파일에서 파일을 작성하는 데 사용됩니다. Make는 대상이 파일이라고 가정하고 Makefile을 작성하는 것이 상대적으로 쉽습니다.
foo: bar
create_one_from_the_other foo bar
그러나 때로는 Makefile이 파일 시스템에서 실제 파일을 나타내지 않는 명령을 실행하기를 원합니다. 이에 대한 좋은 예는 공통 대상 "clean"및 "all"입니다. 그렇지 않을 수도 있지만 clean
기본 디렉토리에 이름이 지정된 파일 이 있을 수 있습니다 . 이러한 경우 기본적으로 clean
대상이이 파일과 연관되고 Make가 파일이 해당 종속성과 관련하여 최신 상태가 아닌 것으로 표시 될 때만이를 실행 하므로 Make가 혼동 됩니다.
이러한 특수 대상을 가짜 라고 하며 파일과 연결되지 않도록 Make와 같이 명시 적으로 말할 수 있습니다.
.PHONY: clean
clean:
rm -rf *.o
지금 make clean
과 같은라는 이름의 파일이 할 경우에도 예상 실행됩니다 clean
.
Make의 관점에서, 가짜 대상은 단순히 오래된 대상이므로 make <phony_target>
파일 시스템의 상태와 관계없이 요청할 때마다 실행됩니다. 일반적인에 make
종종 가짜입니다 목표는 다음과 같습니다 : all
, install
, clean
, distclean
, TAGS
, info
, check
.
install
makefile에서 매우 일반적인 대상 이 있다고 가정 해 봅시다 . 을 사용 하지 않고.PHONY
이름 install
이 지정된 파일 이 Makefile과 동일한 디렉토리에 있으면 아무 것도make install
수행하지 않습니다 . 이는 Make가 규칙을 해석하여 "파일을 생성하기위한 이러한 레시피를 실행하여 install
" 라는 파일을 생성하기 때문 입니다. 파일이 이미 있고 종속성이 변경되지 않았으므로 아무 것도 수행되지 않습니다.
그러나 install
대상을 PHONY로 만들면 make 도구에 대상이 가상임을 알리고 실제 파일을 작성할 것으로 예상해서는 안됩니다. 따라서 install
파일이 존재 하는지 여부를 확인 하지 않습니다. 즉, a) 파일이 존재하면 해당 동작이 변경되지 않으며 b) 추가 stat()
가 호출되지 않습니다.
일반적으로 Makefile에서 대상 이름과 이름이 같은 출력 파일을 생성하지 않는 모든 대상은 PHONY 여야합니다. 이것은 일반적으로 포함 all
, install
, clean
, distclean
, 등.
.sh
하거나 .bash
그들과 같은 실행은 주요 기능 및 예비 당신이 포함 라이브러리의 확장을 (추가 가지고 "프로그램"에 대한 확장 source mylib.sh
). 사실 필자는 Makefile과 같은 디렉토리에install
.PHONY
항상 사용 합니다 ...
.PHONY
버전 임을 깨닫지 못하도록 삽을 가져가는 것이 좋습니다 .
참고 : make 도구는 makefile을 읽고 규칙에서 ':'기호 양쪽에있는 파일의 수정 타임 스탬프를 확인합니다.
'test'디렉토리에는 다음 파일이 있습니다.
prerit@vvdn105:~/test$ ls
hello hello.c makefile
makefile에서 규칙은 다음과 같이 정의됩니다.
hello:hello.c
cc hello.c -o hello
이제 'hello'파일이 'hello.c'파일 다음에 작성된 일부 데이터를 포함하는 텍스트 파일이라고 가정하십시오. 따라서 'hello'의 수정 (또는 생성) 타임 스탬프는 'hello.c'의 타임 스탬프보다 최신입니다. 따라서 명령 행에서 'make hello'를 호출하면 다음과 같이 인쇄됩니다.
make: `hello' is up to date.
이제 'hello.c'파일에 액세스하여 공백을 넣으십시오. 이는 코드 구문이나 논리에 영향을 미치지 않으며 저장하고 종료합니다. 이제 hello.c의 수정 타임 스탬프가 'hello'보다 수정되었습니다. 이제 'make hello'를 호출하면 다음과 같이 명령이 실행됩니다.
cc hello.c -o hello
그리고 'hello'(텍스트 파일) 파일은 새로운 바이너리 파일 'hello'(위의 컴파일 명령의 결과)로 덮어 씁니다.
다음과 같이 makefile에서 .PHONY를 사용하는 경우 :
.PHONY:hello
hello:hello.c
cc hello.c -o hello
그런 다음 'make hello'를 호출하면 pwd 'test'에있는 파일을 무시하고 매번 명령을 실행합니다.
이제 'hello'대상에 선언 된 종속성이 없다고 가정하십시오.
hello:
cc hello.c -o hello
'hello'파일이 이미 pwd 'test'에 존재하면 'make hello'는 항상 다음과 같이 표시됩니다.
make: `hello' is up to date.
make
전체적으로 의미가 있습니다. 파일에 관한 것입니다! 이 답변에 감사드립니다.
.PHONY: install
가장 좋은 설명은 GNU make manual 자체입니다 : 4.6 Phony Targets section .
.PHONY
make의 특수 내장 대상 이름 중 하나입니다 . 관심있는 다른 목표가 있으므로이 참조를 통해 감추는 것이 좋습니다.
.PHONY 대상을 고려해야 할 때 make는 해당 이름의 파일이 존재하는지 또는 마지막 수정 시간이 무엇인지에 관계없이 레시피를 무조건 실행합니다.
또한 메이크업의에 관심이있을 수 있습니다 표준 대상 등 all
과 clean
.
".PHONY"에 대한 하나의 중요한 까다로운 처리 방법이 있습니다. 물리적 대상이 다른 물리적 대상에 의존하는 가짜 대상에 의존하는 경우 :
TARGET1-> PHONY_FORWARDER1-> PHONY_FORWARDER2-> TARGET2
TARGET2를 업데이트 한 경우 TARGET1은 TARGET1에 대해 오래된 것으로 간주되므로 TARGET1을 다시 빌드해야합니다. 그리고 그것은 실제로 이런 식으로 작동합니다 .
까다로운 부분은 TARGET2 가 TARGET1 에 부실 하지 않은 경우입니다.이 경우 TARGET1을 다시 빌드하지 않아야합니다.
:이 의외로 때문에 작동하지 않습니다 (가짜 대상으로 평소의 방법대로) 가짜 대상 어쨌든 실행 된 것을하는 수단, 가짜 대상이 업데이트 간주되었다 . 그리고 그 때문에 TARGET1은 가짜 대상에 대해 오래된 것으로 간주됩니다 .
치다:
all: fileall
fileall: file2 filefwd
echo file2 file1 >fileall
file2: file2.src
echo file2.src >file2
file1: file1.src
echo file1.src >file1
echo file1.src >>file1
.PHONY: filefwd
.PHONY: filefwd2
filefwd: filefwd2
filefwd2: file1
@echo "Produced target file1"
prepare:
echo "Some text 1" >> file1.src
echo "Some text 2" >> file2.src
이것을 가지고 놀 수 있습니다 :
fileall이 가짜 대상을 통해 간접적으로 file1에 의존한다는 것을 알 수 있지만 이 종속성으로 인해 항상 다시 작성됩니다. 에서의 종속성을 fileall
에서 (으) filefwd
로 변경하면 file
이제는 fileall
매번 다시 빌드되지 않고 종속 대상이 파일로 부실한 경우에만 다시 빌드됩니다.
특수 대상을 .PHONY:
사용하면 가짜 대상을 선언 할 수 있으므로 make
실제 파일 이름으로 확인되지 않습니다. 이러한 파일이 여전히 존재하더라도 항상 작동합니다.
당신은 몇 가지 .PHONY:
를 넣을 수 있습니다 Makefile
:
.PHONY: all
all : prog1 prog2
...
.PHONY: clean distclean
clean :
...
distclean :
...
가짜 대상을 선언하는 또 다른 방법이 있습니다 : 간단히 '::'
all :: prog1 prog2
...
clean ::
...
distclean ::
...
은 '::'특별한 의미가 있습니다 대상은 가짜입니다 플러스 그들은 여러 번 나타날 수 있습니다 :
clean ::
rm file1
...
clean ::
rm file2
명령 블록이 차례로 호출됩니다.
나는 종종 그것들을 사용하여 기본 대상에게 발사하지 말라고 지시합니다.
superclean: clean andsomethingelse
blah: superclean
clean:
@echo clean
%:
@echo catcher $@
.PHONY: superclean
가짜없이 make superclean
해고 clean
, andsomethingelse
및 catcher superclean
; 그러나 PHONY를 사용하면를 make superclean
실행하지 않습니다 catcher superclean
.
우리는 clean
목표가 PHONY라는 말을하는 것에 대해 걱정할 필요 가 없습니다. 그것은 완전히 가짜가 아니기 때문입니다. 클린 파일을 생성하지는 않지만 실행 명령이 있으므로 make는 최종 대상이라고 생각합니다.
그러나 superclean
대상은 실제로 가짜이므로 make는 superclean
대상에 대한 깊이를 제공 하는 다른 superclean
대상과 함께 쌓으려고 시도합니다. 여기에는 다른 대상과 대상 이 포함됩니다 %
.
우리는 andsomethingelse
또는 blah
에 대해 아무 말도하지 않으므로 포수에게 분명히 간다.
출력은 다음과 같습니다.
$ make clean
clean
$ make superclean
clean
catcher andsomethingelse
$ make blah
clean
catcher andsomethingelse
catcher blah