2016-07-06 3 views
0

그래서 foo.conf.master라는 마스터 복사본을 기반으로 foo.conf를 설치하는 Makefile이 있습니다.gnu make - 파일의 설치 버전을 파일의 마스터 버전과 일치하도록 만들기

all: foo.conf.copied 

foo.conf.copied: foo.conf.master foo.conf 
     cp foo.conf.master foo.conf 
     touch [email protected] 

# Recipe to tell make that it is okay for foo.conf not to exist beforehand. 
foo.conf: 

그럼 foo.conf.master 생성 : 그것은 단지 테스트 목적으로, 오히려 등/이상 현재 디렉토리에 설치

$ touch foo.conf.master 
$ 

을 당신은 시험 준비 :

$ make 
cp foo.conf.master foo.conf 
touch foo.conf.copied 
$ 

요점은 그 다음 (아마도 크론에 의해 호출) 할 foo.conf.master을 수정 (내 "신뢰할 수있는"시스템 관리자 모자) 나는 업데이트 출시 할 경우 :

$ touch foo.conf.master 
$ make 
cp foo.conf.master foo.conf 
touch foo.conf.copied 
$ 

그러나 똑같이 중요 16,:

$ touch foo.conf 
$ make 
cp foo.conf.master foo.conf 
touch foo.conf.copied 
$ 

사랑 나누기 : (내 "불량"시스템 관리자 모자) 내가 업데이트를 백업 할 수 있도록 다음 설치 버전을 수정하는 경우.

이제는 문제가 있습니다. 분명히 foo.conf가이 작업을 수행하는 유일한 파일이 아니기 때문에 정적 규칙을 패턴 규칙으로 변경해야합니다. 좋아요, 간단합니다 : foo.conf를 대상 및 종속성에서 %로 대체하고, 명령에서 $ * 대신 foo.conf를 사용하고 마지막 레시피를 사소한 수정 ('% :'만 가능)하면되도록 수정합니다 내가 하려고 시도하는 것 같지 않아 내장 패턴 규칙을 취소하십시오.

그래서 정리하고이 Makefile을 만들 :

all: foo.conf.copied 

%.copied: %.master % 
     cp $*.master $* 
     touch [email protected] 

# Recipe to tell make that it is okay for foo.conf not to exist beforehand. 
# Nop tells make that I'm not *cancelling* a pattern rule here 
# (see http://stackoverflow.com/questions/34315150/make-implicit-rules-dont-work-without-command). 
%: ; 

을하지만이 작동하지 않습니다

$ make 
make: *** No rule to make target `foo.conf.copied', needed by `all'. Stop. 
$ 

오류 메시지가 잘못된 것입니다; '

foo.conf: 
     touch [email protected] 

그러나 그 정적 규칙은 내가 돈있는, 다시이다 : 정말 메이크 파일의 맨 아래에 다음을 추가하여 입증 할 수있는, 만드는 방법을 알고하지 않는 파일 foo.conf한다 싶어.

위의 예에서 설명하지 않은 몇 가지 요구 사항이 있습니다. 이들은 :

  • foo.conf의가 파일 시스템에 설치 어디서나 (예 /etc/foo/server/foo.conf)
  • foo.conf.master 중앙 디렉토리에, 또는 subdirectly 그해야해야 (예 : ~/poor-mans-puppet/master-files/etc/foo/foo.conf)가없는 모든 마스터 버전의 경우
  • foo.conf.copied는 중앙 디렉토리에 있어야합니다 같은 디렉토리에 파일 foo.conf (예 : ~/가난한 마르스 - 꼭두각시/타임 스탬프 파일/etc/foo는/파일 foo.conf)

후 많은 인터넷 검색을하지, 머리 당기고, 나는 여기에서 묻고있다! 어떤 아이디어라도 제발? (추신 : 여기에서 Makefile을 복사하는 경우 들여 쓰기를 탭으로 다시 변경해야합니다.)

미친 과학자는 우아한 정적 규칙을 제안했지만 실제로 패턴 규칙이 필요합니다.

all: <new-dependency> 

을 대신 사용하여 변수를 후킹보다 :

STUFF_ALL_SHOULD_DEPEND_ON += <new-dependency> 
이 요구 사항에 대한 이유와 일관성이다

어떻게 다른 (비 이유는 내가 사용 규칙에 추가 종속성을 연결해야한다는 것입니다 % .copied) 타겟은 매우 큰 Makefile에서 처리됩니다.

그러나, 미친 과학자의 아이디어를 기반으로, 나는 작동하지 않았다 다음을 시도했지만 아마도 누군가가 나를 도울하는 데 도움이 :

all: foo.conf.copied 

%.copied: %.master % 
    $(eval FILES_FOR_WHICH_AN_EMPTY_RECIPE_ARE_NEEDED += $$*) 
    cp $*.master $* 
    touch [email protected] 

define GENERATE_STATIC_EMPTY_RULE 
$(1): 
endef 

$(foreach X,$(FILES_FOR_WHICH_AN_EMPTY_RECIPE_ARE_NEEDED),$(eval $(call GENERATE_STATIC_EMPTY_RULE,$(X)))) 

답변

0

당신이 "이 여분을 사용하는 이유를 설명 할 수 있습니다. 복사 된 "파일? 왜 그냥 사용하지 마십시오 :

%: %.master ; cp $< [email protected] 

?

어쨌든, 당신은 match-anything 규칙 (모든 것을 만들 수있는 %과 같은 패턴 규칙)과 관련된 make의 특별한 규칙을 따르고 있습니다. 패턴이 일치하지 않으므로 패턴을 변경하면 %.conf: ;과 같이 작동합니다. 그러나 아마 모든 파일이 .conf으로 끝나는 것으로 가정하고 싶지 않을 것입니다.

다른 방법은 다음과 같이 정적 패턴 규칙을 사용할 수 있습니다

FILES_TO_COPY = foo.conf bar.conf biz.baz 

all: $(FILES_TO_COPY:%=%.copied) 

$(FILES_TO_COPY:%=%.copied): %.copied : %.master % 
     cp $*.master $* 
     touch [email protected] 

당신은 여분의 패턴 규칙이 필요하지 않습니다.

+0

.copied 파일이 필요 내가 foo.conf.master이 * 업데이트입니다 경우 또는 자체가 업데이트됩니다 foo.conf의 * 파일을 다시 복사 할 때문이다. 원래 게시물에서 'rogue'를 검색하십시오. "모든 파일이 .conf로 끝나는 것을 원하지 않을 것입니다.": 사실. –

0

결국 정적 규칙을 동적으로 생성했습니다.

ifeq ($(MAKELEVEL),0) 
all: 
     for X in $(patsubst %.copied,%,$^); do \ 
      echo "$$X.copied: $$X.master $$X"; \ 
      echo "  cp $$X.master $$X"; \ 
      echo "  touch \[email protected]"; \ 
      echo "$$X: ;"; \ 
     done > Makefile.include 
     $(MAKE) 

# The real dependencies on all are defined below, but while creating 
# Makefile.include, we don't want make to digress and start making 
# the dependencies; this pattern rule will stop it from doing that. 
%.copied: ; 
else 
include Makefile.include 
endif 

all: foo.conf.copied 

외부 메이크업은 .SILENT의 사용에 의해 침묵과 --no-print-directory 옵션 (도시 생략 할 수 있습니다

if flag not set     # flag won't be set on first call 
    prepare static rules 
    set flag      # prevent running this clause again 
    recurse!      # make invokes make 
else 
    include static rules 
    do the normal thing 
endif 

여기에 실제 메이크 파일의 다음의 의사 코드는 희망 쉽게 실제 메이크 이해 할 수 있습니다 명확성을 위해 위의 내용 참조).

다음은 출력입니다 :

$ touch foo.conf.master 
$ make 
cp foo.conf.master foo.conf 
touch foo.conf.copied 
$ touch foo.conf 
$ make 
cp foo.conf.master foo.conf 
touch foo.conf.copied 
$