makefile에서 .PHONY의 목적은 무엇입니까?


1737

.PHONYMakefile에서 무엇을 의미합니까? 나는 이것을 겪었 지만 너무 복잡하다.

누군가 간단한 용어로 설명해 줄 수 있습니까?

답변:


1945

기본적으로 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.


49
@ eSKay : '왜'포니 '라고 불리는가?' -실제 목표가 아니기 때문입니다. 즉, 대상 이름은 해당 대상의 명령으로 생성 된 파일이 아닙니다.
Bernard

96
@Lazer : 당신이 영어 원어민인지 모르겠습니다. 난 아니에요. '포니'라는 단어가 그 소리를 의미하지는 않습니다. en.wiktionary.org/wiki/phony의 말 : 사기성; 모조품; 오해의 소지가 있습니다.
Bahbar

57
이 답변은 완벽하지는 않습니다. 링크 된 자습서에서 다룰 수도 있습니다. .PHONY는 Makefile의 레이블 / 파일이 대상이 무엇이든 토폴로지 정렬 된 일부인 경우 빌드되도록합니다. 즉, '정리'로 설정된 '정리 :'레이블이 있고 설치 레이블이 정리와 함께 필수 조건 (예 : '설치 : 정리')으로 정의 된 경우, Makefile이 빌드를 시도 할 때 정리가 항상 실행됩니다. '설치'. 성공 여부와 상관없이 항상 원하는 단계에 유용합니다. 타임 스탬프를 무시하고 강제로 적용합니다.
신디사이저

9
작업과 이름이 같은 파일이 없으면 .PHONY를 사용할 필요가 없습니다. 작업은 항상 어쨌든 실행되며 Makefile은 더 읽기 쉽습니다.
Bernard

15
"위조 대상은 단순히 오래된 대상입니다"-훌륭한 설명!
Danijel

730

installmakefile에서 매우 일반적인 대상 이 있다고 가정 해 봅시다 . 을 사용 하지 않고.PHONY 이름 install이 지정된 파일 이 Makefile과 동일한 디렉토리에 있으면 아무 것도make install 수행하지 않습니다 . 이는 Make가 규칙을 해석하여 "파일을 생성하기위한 이러한 레시피를 실행하여 install" 라는 파일을 생성하기 때문 입니다. 파일이 이미 있고 종속성이 변경되지 않았으므로 아무 것도 수행되지 않습니다.

그러나 install대상을 PHONY로 만들면 make 도구에 대상이 가상임을 알리고 실제 파일을 작성할 것으로 예상해서는 안됩니다. 따라서 install파일이 존재 하는지 여부를 확인 하지 않습니다. 즉, a) 파일이 존재하면 해당 동작이 변경되지 않으며 b) 추가 stat()가 호출되지 않습니다.

일반적으로 Makefile에서 대상 이름과 이름이 같은 출력 파일을 생성하지 않는 모든 대상은 PHONY 여야합니다. 이것은 일반적으로 포함 all, install, clean, distclean, 등.


6
@PineappleUndertheSea 허용되는 답변은 초기 무가치 수준에서 크게 개선되었으며 이제는 이만큼이나 좋습니다. 귀하의 의견을 이해하기 위해 개정 내역을 살펴 봐야했습니다.
Mark Amery

2
내 코드베이스에 'install'등의 파일이 절대 없기 때문에 이것은 의미가 없습니다. 대부분의 파일은 파일 확장자를 갖게되며 파일 확장자가없는 파일은 일반적으로 'README'와 같이 모든 대문자로 표시됩니다. 그런 다음 'install.sh'대신 'install'이라는 bash 스크립트가 있으면 시간이 나쁠 것입니다.
nucleartide

6
@JasonTu 반드시 그런 것은 아닙니다. 배쉬 스크립트 규칙은 생략하도록 요청 .sh하거나 .bash그들과 같은 실행은 주요 기능 및 예비 당신이 포함 라이브러리의 확장을 (추가 가지고 "프로그램"에 대한 확장 source mylib.sh). 사실 필자는 Makefile과 같은 디렉토리에install
카일 (Kyle)

10
@Kyle 예, 과거의 자기 자신이 무엇을 의미하는지 잘 모르겠습니다. 요즘 나는 .PHONY항상 사용 합니다 ...
nucleartide

2
@JasonTu 여기에 해결책은 간단합니다. 타임머신을 구축하고 과거의 자아를 "대체"하십시오. 아무도 당신이 .PHONY버전 임을 깨닫지 못하도록 삽을 가져가는 것이 좋습니다 .
Mateen Ulhaq 2018 년

120

참고 : 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.

3
이것은 내가 실행하는 명령을 의미있게 만들뿐만 아니라 결국 make전체적으로 의미가 있습니다. 파일에 관한 것입니다! 이 답변에 감사드립니다.
Kzqai

80
.PHONY: install
  • "install"이라는 단어가이 Makefile의 파일 이름을 나타내지 않음을 의미합니다.
  • Makefile은 동일한 디렉토리에있는 "install"이라는 파일과 아무 관련이 없음을 의미합니다.

45

파일 이름이 아닌 빌드 대상입니다.


33

가장 좋은 설명은 GNU make manual 자체입니다 : 4.6 Phony Targets section .

.PHONYmake의 특수 내장 대상 이름 중 하나입니다 . 관심있는 다른 목표가 있으므로이 참조를 통해 감추는 것이 좋습니다.

.PHONY 대상을 고려해야 할 때 make는 해당 이름의 파일이 존재하는지 또는 마지막 수정 시간이 무엇인지에 관계없이 레시피를 무조건 실행합니다.

또한 메이크업의에 관심이있을 수 있습니다 표준 대상allclean.


11

".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

이것을 가지고 놀 수 있습니다 :

  • 먼저 "소스 파일"을 준비하기 위해 'make ready'
  • 특정 파일을 터치하여 업데이트 된 파일을보고

fileall이 가짜 대상을 통해 간접적으로 file1에 의존한다는 것을 알 수 있지만 이 종속성으로 인해 항상 다시 작성됩니다. 에서의 종속성을 fileall에서 (으) filefwd로 변경하면 file이제는 fileall매번 다시 빌드되지 않고 종속 대상이 파일로 부실한 경우에만 다시 빌드됩니다.


5

특수 대상을 .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

명령 블록이 차례로 호출됩니다.


3

나는 종종 그것들을 사용하여 기본 대상에게 발사하지 말라고 지시합니다.

superclean: clean andsomethingelse

blah: superclean

clean:
   @echo clean

%:
   @echo catcher $@

.PHONY: superclean

가짜없이 make superclean해고 clean, andsomethingelsecatcher 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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.