2011-01-12 3 views
2

.PHONY 타겟과의 전투에서 나는 다음과 같이 썼다.Makefile : tar 파일을 만들 때 디렉토리 내용에 대한 의존성

# Makefile v0 

tar: 
    tar -cf tarfile.tar dir 

.PHONY: tar 

:

# Makefile v1 

tar: tarfile.tar 

tarfile.tar: $(shell find dir) 
    tar -cf [email protected] dir 

.PHONY: tar 

장난감 예제에서 작동하는 것처럼 보입니다.

그러나 $(shell find dir)가 평가되는 시간에 따라 이것이 잘못된 것을 할 수 있음을 알 수 있습니다. Makefile이 파싱 된 후 dir에서 파일을 만들거나 삭제하는 규칙이있는 경우이 문제가 발생할 수 있습니다.


업데이트

@ user562374의 답을 바탕으로 더 나은 해결책이있는 것 같습니다.이 경우를 고려해보십시오.

# Makefile v2 

tar: tarfile.tar 

tarfile.tar: dir/.dirstamp 
    tar --create --exclude $< --file [email protected] $(<D) 

dir/.dirstamp: .FORCE 
    [ ! -e [email protected] -o "$(find $(@D) -newer [email protected] -print -quit)" ] && touch [email protected] 

dir/a: src/a 
    cp $< [email protected] 

.FORCE: 
.PHONY: .FORCE tar 

이제 src/a이 변경되었다고 가정합니다. tarfile.tardir/a (직접 또는 간접이 아님)간에 종속성이 없으므로 tarfile.tar: 대상은 dir/a: 이전에 평가 될 수 있으므로 tarfile.tar은 최신이 아닙니다.


그럼, 내 질문은 : 이러한 경우를 다루는 가장 좋은 방법은 무엇입니까? dir에있는 파일 목록을 별도로 유지해야합니까? 그렇다면 가장 쉬운 방법은 무엇입니까?

답변

2

내가 사용하는 방법입니다.

.PHONY: .FORCE 
.FORCE: 

dirstamp: .FORCE 
     hxdirstamp subdir/ >[email protected]; \ 
     cmp -s [email protected] [email protected] || mv [email protected] [email protected]; \ 
     rm -f [email protected]; 

my.tar: dirstamp 
     tar -cf [email protected] subdir/; 

또한 dirstamping 대신 ls -Rl를 사용하지만 로케일 허가 및 크기 변경 (모든 단지 메이크업 의존성을했다, 어느 무시 될 것이다)에서 영향을 될 수 있음을 인식 할 수있다.

+2

니스. 이 답변을 바탕으로 collègue는'dirstamp' 대상에 대한 최적화 된 제조법을 제시했습니다. -e $ @ -o "$ (find subdir/-newer $ @ -print -quit)"] && touch $ @' –

0

이유는 바로 그 때 dir/이보다 최신 파일이 포함 tarfile.tar.PHONY로 표시하지?

$(if $(shell find dir -type f -newer file.tar),$(eval .PHONY: file.tar)) 
file.tar: ; tar cvf [email protected] dir/ 

은 (어쩌면 ! -type d-type f보다 약간 더 나은 것,하지만 당신은 아이디어를 얻을.)

+0

왜 이것이'Makefile v2'보다 좋을까요? 'src/a'가 변경되었을 때 어떻게 실패를 해결합니까? 또한 * dir의 하위 디렉토리에 파일 추가/제거를 지원하기 위해 * 결과적으로 검색 결과를'type f' (또는'! -type d ')로 제한하지 않았습니다. –

+0

사실, 이것은 Makefile v1과 매우 유사합니다. 사실 위의 제안에 v1의 2 선을 선호합니다. V2는 단순히 고장났습니다. v2에서는'dir/a '에 대한 레시피를 실행하면'tarfile.tar'에 대한 레서피를 실행할 필요가 있다고 말하지 않았습니다. 이것은 매우 약해서 _n_의 일부 값에 대해서 조용하게 실패 할 것입니다 (find 식에서'$'를 두배로 늘릴 필요가 있습니다 :'$$ (find ...)'). – bobbogo

관련 문제