makefile이 대상을 재 빌드하도록 강제하는 방법


184

빌드하고 다른 makefile을 호출하는 makefile이 있습니다. 이 makefile은 작업을 수행하는 더 많은 makefile을 호출하므로 실제로 변경되지 않습니다. 따라서 프로젝트가 최신 상태로 유지되고 있다고 생각합니다.

dnetdev11 ~ # make
make: `release' is up to date.

makefile이 대상을 다시 빌드하도록하려면 어떻게해야합니까?

clean = $(MAKE) -f ~/xxx/xxx_compile.workspace.mak clean


build = svn up ~/xxx                                                       \
        $(clean)                                                                \
        ~/cbp2mak/cbp2mak -C ~/xxx ~/xxx/xxx_compile.workspace        \
        $(MAKE) -f ~/xxx/xxx_compile.workspace.mak $(1)                    \


release:
        $(build )

debug:
        $(build DEBUG=1)

clean:
        $(clean)

install:
        cp ~/xxx/source/xxx_utility/release/xxx_util /usr/local/bin
        cp ~/xxx/source/xxx_utility/release/xxxcore.so /usr/local/lib

참고 : 무고한 사람을 보호하기 위해 이름이 제거되었습니다.

편집 : 최종 고정 버전 :

clean = $(MAKE) -f xxx_compile.workspace.mak clean;


build = svn up;                                         \
        $(clean)                                        \
        ./cbp2mak/cbp2mak -C . xxx_compile.workspace;   \
        $(MAKE) -f xxx_compile.workspace.mak    $(1);   \


.PHONY: release debug clean install

release:
        $(call build,)

debug:
        $(call build,DEBUG=1)

clean:
        $(clean)

install:
        cp ./source/xxx_utillity/release/xxx_util /usr/bin
        cp ./dlls/Release/xxxcore.so /usr/lib

Lodle, 이것은 자주 방문하는 질문이므로 질문을보다 현대적인 것으로 편집 하시겠습니까? (이것이 .PHONY유일한 문제는 아닌 것처럼 보였고 실제로 솔루션을 질문에 편집하거나 더 이상은 아닙니다.)
Keith M

답변:


23

하나 이상의 대상을 가짜라고 선언 할 수 있습니다 .

가짜 대상은 실제로 파일 이름이 아닌 대상입니다. 오히려 명시적인 요청을 할 때 레시피가 실행되는 이름 일뿐입니다. 가짜 대상을 사용해야하는 두 가지 이유가 있습니다. 동일한 이름의 파일과의 충돌을 피하고 성능을 향상시키는 것입니다.

...

가짜 대상은 실제 대상 파일의 전제 조건이 아니어야합니다. 그렇다면 파일을 업데이트 할 때마다 레시피가 실행됩니다. 가짜 대상이 실제 목표의 전제 조건이 아닌 한, 가짜 대상 레시피는 가짜 대상이 지정된 목표 인 경우에만 실행됩니다.


68
이 답변은 "허용되고"높은 평가를 받았지만 실제로는 별다른 의미가 없습니다. 먼저 "대상을 가짜로 선언"이라고 말한 다음 "포니 대상은 실제로 파일 이름이 아닙니다"라고 말합니다. 글쎄, 당신의 목표가 파일이라면, 그것은 대답의 모순입니다. 둘째, "포니 대상은 실제의 전제 조건이되어서는 안된다"고 말합니다. 그렇다면 어떻게해야합니까? 원래 질문은, 그렇지 않은지를 지정하지 않았습니다. 정답은있다, 없다 선언하는 당신 가짜로 목표를 아니라, 추가 가짜 목표를 선언 한 다음, 그 위에, 당신은 다시 원하는 대상을 따라 달라집니다.
Mark Galeck

2
@MarkGaleck. 대답에 "가짜 파일은 실제로 파일 이름이 아닙니다"라는 메시지가 표시되면 gcc make manual에서 직접 인용합니다. 완벽하게 맞습니다.
drlolly

"대상"은 :생성하려는 최종 결과 (예 : 이진 파일)뿐만 아니라 콜론 왼쪽의 텍스트를 나타내는 Make 용어입니다 . 질문에서, release, debug, clean, 및 install만들기 목표,하지 xxx_util또는 xxxcore.so그렇지 않으면 아무것도.
Keith M

728

-B그 긴 형태의 메이크업에 스위치는 --always-make, 알 make무시 타임 스탬프에 지정된 목표를합니다. 이것은 make를 사용하는 목적을 상실 할 수도 있지만 필요한 것일 수도 있습니다.


4
@MarkKCowan 나는 완전히 동의한다! 이 옵션은 Dave가 제안한대로 해결 방법이 아닌 내가 찾던 것입니다.
Maarten Bamelis 2016 년

8
이 접근 방식의주의 사항은 너무 많은 것을 구축한다는 것입니다. 특히 autotools를 사용하면 configure을 다시 실행하는 것을 보았습니다. LD_PRELOAD 기반 솔루션을 빌드 할 수 있기를 바랍니다 !!
vrdhn

예, 원하지 않는 파일을 다시 쓸 수도 있습니다! 의존성에 나타나고 재 구축되고 덮어 쓰기되는 글로벌 시스템 라이브러리와 같은 것
Julio Guerra

18

Sun 매뉴얼에 문서화되어 make왔던 한 가지 트릭은 존재하지 않는 대상 '.FORCE'를 사용하는 것입니다. 다음을 포함하는 force.mk 파일을 작성하여이를 수행 할 수 있습니다.

.FORCE:
$(FORCE_DEPS): .FORCE

그런 다음 기존 makefile이라고 가정하면 다음을 makefile실행할 수 있습니다.

make FORCE_DEPS=release -f force.mk -f makefile release

.FORCE존재하지 않기 때문에 그것에 의존하는 것은 오래되고 재건됩니다.

이 모든 것은 모든 버전의 make; Linux에는 GNU Make가 있으므로 논의 된대로 .PHONY 대상을 사용할 수 있습니다.

make릴리스가 최신 버전 인 이유를 고려해야합니다. touch release실행 된 명령 중에 명령 이 있기 때문일 수 있습니다 . 'release'라는 파일 또는 디렉토리가 존재하고 종속성이 없으며 최신 버전이기 때문일 수 있습니다. 그렇다면 실제 이유가 있습니다 ...


14

다른 사람이 .PHONY를 제안했는데 이는 옳습니다. .PHONY는 입력과 출력 간의 날짜 비교가 유효하지 않은 규칙에 사용해야합니다. 양식의 대상이 없으므로 모든 대상에 output: input.PHONY를 사용해야합니다!

말했듯이, 아마도 다양한 파일 이름에 대해 makefile 상단에 일부 변수를 정의하고 입력 및 출력 섹션이 모두있는 실제 make 규칙을 정의하여 make의 이점을 사용할 수 있습니다. 즉 실제로 컴파일 만합니다. copmile에 필요한 것들!

편집 : 예를 추가했습니다. 테스트되지 않았지만 이것이 당신이하는 방법입니다.

.PHONY: clean    
clean:
    $(clean)

1
글쎄, 당신이 나에게 예를 보여줄 수 있다면 그것은 좋을 것입니다. Atm im 그냥 댐 일을하려고 해킹 해킹 : P
Lodle

1
.PHONY대상 의 위치는 중요하지 않습니다. 의 어느 곳에 나있을 수 있습니다 Makefile.
애드리안 W

5

올바르게 기억한다면 'make'는 타임 스탬프 (파일 수정 시간)를 사용하여 대상이 최신인지 여부를 결정합니다. 재 빌드를 강제하는 일반적인 방법은 'touch'명령을 사용하여 해당 타임 스탬프를 업데이트하는 것입니다. Makefile에서 'touch'를 호출하여 대상 중 하나 (아마 하위 하위 파일 중 하나)의 타임 스탬프를 업데이트하면 Make가 해당 명령을 강제로 실행할 수 있습니다.


5

이 간단한 기술을 사용하면 강제 실행을 원하지 않을 때 makefile이 정상적으로 작동 할 수 있습니다. makefile 끝에 force 라는 새 대상을 작성하십시오 . 힘의 대상이 기본 대상에 의존하는 파일을 터치합니다. 아래 예제에서 touch myprogram.cpp를 추가했습니다 . 또한 재귀 호출을 추가 하기를 . 이렇게하면 make force 를 입력 때마다 기본 대상이 만들어집니다 .

yourProgram: yourProgram.cpp
       g++ -o yourProgram yourProgram.cpp 

force:
       touch yourProgram.cpp
       make

makeMakefile 내부에서 사용해서는 안됩니다 . $(MAKE)대신 사용하십시오 .
Benjamin Crawford Ctrl-Alt-Tut

3

나는 이것을 시도했고 그것은 나를 위해 일했다.

이 줄을 Makefile에 추가하십시오

clean:
    rm *.o output

new: clean
    $(MAKE)     #use variable $(MAKE) instead of make to get recursive make calls

저장하고 지금 전화

make new 

다시 모든 것을 다시 컴파일합니다

어떻게 된 거예요?

1) '새로운'통화가 깨끗합니다. 'clean'do 'rm'은 확장자가 '.o'인 모든 오브젝트 파일을 제거합니다.

2) '신규'는 'make'를 호출합니다. 'make'는 '.o'파일이 없다는 것을 알기 때문에 모든 '.o'를 다시 만듭니다. 링커는 모든 .o 파일을 하나의 실행 가능한 출력으로 연결합니다.

행운을 빕니다


1
보다 new나은 사용을 위한 레시피$(MAKE)make
Basile Starynkevitch

1

Miller 's Recursive Make Harmful에 따르면 전화를 피해야합니다 $(MAKE)! 이 경우 실제로 makefile이 아니고 랩퍼 스크립트 일 뿐이므로 Shell로 작성되었을 수도 있기 때문에 무해합니다. 그러나 당신은 더 깊은 재귀 수준에서 그렇게 계속한다고 말합니다. 그래서 아마도 그 눈을 뜨는 에세이에 표시된 문제에 직면했을 것입니다.

물론 GNU에서는 피하는 것이 번거 롭습니다. 그리고이 문제를 알고 있지만 문서화 된 방식으로 작업을 수행합니다.

OTOH, makepp 는이 문제에 대한 해결책으로 만들어졌습니다. 디렉토리 단위로 makefile을 작성할 수는 있지만 모두 프로젝트의 전체보기로 구성됩니다.

그러나 레거시 makefile은 재귀 적으로 작성됩니다. 따라서 $(MAKE)하위 요청을 기본 makepp 프로세스로 다시 보내는 것 외에는 아무것도 할 수없는 해결 방법이 있습니다. 서브 메이크간에 중복되거나 모순되는 일을하는 경우에만 요청해야합니다 --traditional-recursive-make(물론 makepp의 장점을 어 기고 있음). 나는 당신의 다른 makefile을 모르지만, 그것들이 깨끗하게 작성되면 makepp로 필요한 재 구축이 다른 사람들이 제안한 해킹없이 자동으로 발생해야합니다.


질문에 대답하지 않았습니다 : 요점에 접하고 대답이 아닌 의견이어야합니다.
flungo

어쩌면 나는 충분히 명확하지 않았다. makepp를 사용하면 이 전체 래퍼 makefile이 필요하지 않습니다. 정확한 종속성 (. 다음에 나열된 항목뿐만 아니라 모든 종속성)을 알고 :있으면 필요할 때 항상 다시 빌드됩니다.
Daniel

1

이미 성공적으로 컴파일 한 출력을 보존 할 필요가없는 경우

nmake /A 

모두 재건


0

실제로 목표가 무엇인지에 달려 있습니다. 가짜 대상인 경우 (예 : 대상이 파일과 관련이없는 경우) .PHONY로 선언해야합니다.

그러나 대상이 가짜 대상이 아니지만 어떤 이유로 (예를 들어 __TIME__ 전처리 매크로를 사용하는 경우) 대상을 다시 작성하려는 경우 여기 답변에 설명 된 FORCE 체계를 사용해야합니다.



0

이미 언급되었지만 사용에 추가 할 수 있다고 생각했습니다. touch

touch컴파일 할 모든 소스 파일 인 경우 touch명령은 파일의 타임 스탬프를 touch명령이 실행 된 시스템 시간으로 변경합니다 .

소스 파일 timstamp는 make파일이 변경된 것을 "인식"하는 데 사용되며 다시 컴파일해야합니다.

예를 들어 : 프로젝트가 c ++ 프로젝트 인 경우 do를 수행 touch *.cpp한 후 make다시 실행 하면 make가 전체 프로젝트를 다시 컴파일해야합니다.


0

abernier가 지적했듯이 GNU make 매뉴얼에는 권장되는 솔루션이 있습니다.이 솔루션은 '가짜'대상을 사용하여 대상을 다시 작성합니다.

clean: FORCE
        rm $(objects)
FORCE: ; 

다른 종속성에 관계없이 깨끗하게 실행됩니다.

매뉴얼의 솔루션에 세미콜론을 추가했습니다. 그렇지 않으면 빈 줄이 필요합니다.


-1

내 Linux 시스템 (Centos 6.2)에서는 규칙이 실제로 대상과 일치하는 파일을 작성할 때 대상 .PHONY를 선언하고 FORCE에 대한 가짜 종속성을 작성하는 것 사이에 중요한 차이가 있습니다. 파일을 매번 재생성해야 할 때 파일에 대한 가짜 종속성 FORCE와 가짜 종속성에 대한 .PHONY가 모두 필요했습니다.

잘못된:

date > $@

권리:

FORCE
    date > $@
FORCE:
    .PHONY: FORCE

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.