2010-07-02 4 views
2

같은 소스 파일에서 여러 대상을 만드는 작은 프로젝트가 있습니다. 타겟은 다른 컴파일 플래그로 소스 파일을 빌드해야합니다. 이것은 실제로 cygwin에있다. 그래서 나는 이것을 일반적인 문제라고 생각하지만 구체적인 예로서 사용할 것이다. 여러 개의 MAKE 대상이있는 Makefile에서 올바른 설정으로 오브젝트 파일을 컴파일하는 방법

그래서이 예제 메이크 다음과 같습니다

a: CFLAGS = 

a: a.o c.o 

b: CFLAGS = -mno-cygwin 

b: b.o c.o 

이것은가 설정 CFLAGS와 함께 컴파일 구축, 원칙적으로 작동하고, 건물 B는 -mno-Cygwin에서 설정 CFLAGS 컴파일합니다. 그러나 c.o가 아직 존재하지 않는 경우에만. 그래서 처녀 디렉토리에

> make a b 

을하고

먼저 빈 CFLAGS를 사용하여 A.C 및 c.c을 컴파일합니다. 그런 다음 CFLAGS = -mno-cygwin을 사용하여 b를 빌드하려고합니다. 그러나 c.o가 이미 존재하기 때문에 오브젝트 파일이이 플래그의 동일한 설정을 가져야하므로 c.c를 다시 컴파일하지 않아 링커 오류가 발생합니다.

다시, cygwin-flag는 하나의 구체적인 예일 뿐이며 일반적인 해결책을 찾고 있습니다. 일치하지 않는 경우에 내가 시도 무엇

현재 CFLAGS를 확인하는 추가 대상을 소개하고 모든 오브젝트 파일을 제거하는 것입니다 :

ARCH = `echo $(CFLAGS)` 
checkTarget: 
[email protected] test "`cat .arch`" != "$(ARCH)"; then \ 
    rm *.o; \ 
    /bin/echo -n $(ARCH) > .arch; \ 
fi 

을 두 목표에 대한 종속성으로이 목표를 삽입하는 모든 오브젝트 보장 파일은 필요한 경우 다시 컴파일됩니다.

a: CFLAGS = 

a: checkTarget a.o c.o 

b: CFLAGS = -mno-cygwin 

b: checkTarget b.o c.o 

이 그러나 불필요 모든 오브젝트 파일을 재 컴파일하고, 더 큰 프로젝트에서 문제가된다.

더 좋은 방법이 있나요?

편집 : 단일 답변에 대한 의견에는 CFLAGS의 내용에 따라 개체 파일을 만들 수 있다는 힌트가 포함되어 있습니다. 임시 파일을 cat'ing하고 이전 파일과 비교 한 다음 종속 파일을 통해 복사하는 것을 제외하고는 어떻게해야 하는지를 알 수 없습니다. 더 좋은 방법이 없을까요?

답변

0

이 있지만 곳으로 지적 내가 처음에 (here을 위해 무엇을 요구하는 방법에 대한 몇 가지 제안 ~ slowdog), 나는 Beta의 다른 이름 스키마를 한 걸음 더 나아가도록 결정했고, this question에 대한 대답에서 Beta의 두 번째 제안에 대한 설명을 따르는 하위 ​​디렉토리의 다양한 변형에 대한 모든 객체를 넣었습니다. 내 메이크 모양을 만들어 본질적으로

: 첫 번째 부분 이름을 그래서

A : AOBJDIR = .a 
AOBJECTS = $(addprefix $(AOBJDIR)/,$(ASRCS:.c=.o)) 

$(AOBJECTS): $(AOBJDIR)/%o: %.c 
    $(CC) $(CFLAGS) -MMD -o [email protected] -c $< 

$(AOBJDIR) : 
    @mkdir $(AOBJDIR) 

-include $(AOBJECTS:.o=.d) 

a: $(AOBJDIR) $(AOBJECTS) 
    $(LINK) ... 

하위 디렉토리는 'A'의 오브젝트 파일에 사용하고, 변환하여 디렉토리의 오브젝트 파일의 목록을 생성합니다 소스 파일 이름을 지정하고 서브 디렉토리 접 두부를 추가하십시오.

그런 다음 해당 개체 파일에 대한 기본 규칙 (좋은 측정을 위해 종속성을 생성 함)을 따르십시오.

다음 두 가지는 하위 디렉토리가 존재하는지 확인하고 종속성 정보가 포함되도록합니다.

마지막으로 서브 디렉토리 자체에 대한 추가 종속성이있는 링크 룰이 존재하지 않으면 작성되도록하십시오.

이 블록은 내 예에서 모든 a를 교환하여 b에 대해 반복 할 수 있습니다. 따라서이 블록을 매개 변수화 할 수있는 좀 더 일반적인 것으로 패키지하는 방법을 알아낼 수만 있다면 행복 할 것입니다.

2

여기서 필요한 것은 다른 플래그로 컴파일되고 다른 실행 파일에 링크되도록 c.o의 두 가지 (또는 그 이상) 버전입니다. 당신은 c_for_a.o 같은 인위적인 파일 이름이 작업을 수행 할 수 있지만, 다른 디렉토리에 for_a/for_b/ 그들을 유지하기 위해 정돈의 :

a for_a/%: CFLAGS = 

a: a.o for_a/c.o 

b for_b/%: CFLAGS = -mno-cygwin 

b: b.o for_b/c.o 

(이 명확하지 않으면 나는 메이크의 나머지 부분에서 채울 수 있습니다.)

편집 : 당신은 유지하지 않으려면
여러 c.o의, 당신은 때때로 공동을 다시 컴파일해야합니다. checkTarget 아이디어에는 약간의 개선이 있습니다.

당신이 b 같은 목표를 구축하고

c.o 이미 그 c.ob에 적합한 CFLAGS로 구축되었는지 여부를 중요하고, 해당 정보를 기록 checkTarget를 사용하여 존재한다. 그러나 bCFLAGS에 대해서만 CFLAGS을 사용했는지 상관하지 않습니다. 그래서 당신은 당신이 새로운 목표 빌드 할 때 그냥 업데이트는 checkTarget 파일에 아무것도 기록하지 않아도 :

a: CFLAGS = 

b: CFLAGS = -mno-cygwin 

# You may be able to combine the a and b rules... 
a: a.o c.o checkTarget 
    # build c.o 
    touch checkTarget 
    # build the target 

b: b.o c.o checkTarget 
    # build c.o 
    touch checkTarget 
    # build the target 

# Need this to create checkTarget the first time 
checkTarget: 
    @touch [email protected] 
+0

좋은 답변입니다. 프로젝트가 크고 50 개의 오브젝트 파일이라면, 재 컴파일 할 파일 (이 예제에서는 c.c) 수가 적 으면이 작업이 가능합니다. 대다수가 재 컴파일을 요구한다면,이 전략은 서툴러 질 것이라고 생각합니다. 그 시나리오에 대한 아이디어가 있습니까? – thoni56

+0

@Thomas Nilsson : 최적화하려는 대상에 따라 다릅니다. 'c.c'를 꼭 다시 컴파일하고 싶지 않다면, 다른 버전을 유지해야하며, 이것이 최선의 방법입니다. 여러개의'c.o '를 유지하고 싶지는 않지만 꼭해야 할 때만'c.o'를 다시 컴파일하기를 원한다면, 다른 방법이있다. checkTarget을 조금 개선하면된다. 나는 그것을 포함시키기 위해 나의 대답을 편집 할 것이다. – Beta

+0

흠, 올바르게 이해하면 checkTarget은 타임 스탬프이므로 예 : b를 빌드했지만 b.o와 c.o가 있으면 checkTarget은 여전히 ​​빌드 규칙을 트리거합니다. 그런 다음 명령에서 CFLAGS에 따라 c.o 빌드를 하드 와이어합니다. 만약 당신의 의도라면, 완전히 만족스럽지는 않습니다. (그러나 다시는 가능하지 않을 수도 있습니다 ;-) 왜냐하면 필자의 요구 사항이 변경됨에 따라 명시 적으로 빌드 명령을 업데이트해야하기 때문입니다. 나는 모든 % .o를 컴파일하는데 사용 된 CFLAGS에 의존적으로 만들고, CFLAGS가 동일하지 않은 경우에만 컴파일되도록하는 방법을 찾고 있었다. – thoni56

관련 문제