2013-05-24 4 views
9

makefile을 설정하는 방법을 배우고 있으며 문제가 발생했습니다. 이를 증명하기 위해 소스 파일 main.mtest.m으로 구성된 간단한 "프로젝트"를 만들었습니다.Makefile은 항상 파일을 다시 컴파일합니다.

나는 이러한 파일을 (일도가 변경된 경우에만) 컴파일하고 (여기 build/)을 다른 곳에서 객체 파일을 저장할 수 있도록 설정하려고

내 메이크 :

OBJ = ./build 

SOURCES=main.m test.m 
OBJECTS=$(addprefix $(OBJ)/,$(SOURCES:.m=.o)) 
EXECUTABLE=test 

all: $(EXECUTABLE) 

$(EXECUTABLE): $(OBJECTS) 
     gcc $(OBJECTS) -o $(EXECUTABLE) 

$(OBJECTS): $(OBJ)/%.o: %.m build/ 
     gcc -c $< -o [email protected] 

build/: 
     mkdir build 

내가 실행

gcc -c main.m -o build/main.o 
gcc -c test.m -o build/test.o 
gcc ./build/main.o ./build/test.o -o test 

을 그러나 내가를 실행하는 경우 : 그것은 (단지 메이크와 현재 디렉토리에있는 소스) 처음으로 내가 그것을 할 기대하지다시 :

gcc -c main.m -o build/main.o 
gcc ./build/main.o ./build/test.o -o test 

무엇이 잘못 되었습니까? 또한 "좋은"Makefile을 만드는 법을 배우기 위해 Makefile에있는 다른 오류에 대해서도 언급 할 것입니다.

편집 :

Finished prerequisites of target file `build/main.o'. 
Prerequisite `main.m' is older than target `build/main.o'. 
Prerequisite `build/' is older than target `build/main.o'. 
No need to remake target `build/main.o'. 

Finished prerequisites of target file `build/test.o'. 
Prerequisite `test.m' is older than target `build/test.o'. 
Prerequisite `build/' is newer than target `build/test.o'. 
Must remake target `build/test.o'. 
+0

당신이 단지'/'A의 build' '에 연결하지 않으려는 생각 몇 군데. 내가 여기서 그것을 시도하자. 'make -d'를 사용하여'make '가 무엇을 만들지에 대한 결정을 어떻게 내리는 지 볼 수 있습니다. –

+0

감사합니다. 그러나'make -d' 라우트는 927 줄의 정보를 출력하므로 잠시 시간이 걸릴 것입니다 : – varesa

+0

posisble과 같은 많은 암시적인 규칙을 없앰으로써 조용히 할 수 있습니다. 난 그냥 간단한 테스트 프로젝트와 함께 여기에 귀하의 메이크 파일을 시도하고, 그것은 예상대로 작동하는 것 같았다. 즉, 두 번째 달리기에서, 나는 단지 'make :'all '을 위해 할 일은 아무것도 없다.' –

답변

9

귀하의 make -d 출력 make이 빌드 디렉토리가 업데이트되었습니다 생각, 그래서 그 파일에 필요한 것을 보여줍니다 : 나는 make -d에서 발견 무엇

재건 될

빌드 시스템의 일부 또는 파일 시스템의 일부 조작으로 인해 해당 디렉토리에서 업데이트 할 시간이 생길 수 있습니다.

당신은 그 규칙에 |를 추가하여 위해 전용 전제 조건build을함으로써 문제를 해결할 수 있습니다

$(OBJECTS): $(OBJ)/%.o: %.m | build 

내가 너무 /을 삭제, 그것은 아무것도 안하고 이후.

당신이 질문 때문에, 다른 편집 노트 :

  1. clean 대상을 추가합니다. 뭔가 같이 : 당신이 OBJ을 설정할 때

    clean: 
        rm -rf $(EXECUTABLE) $(OBJ) 
    
  2. 당신은 ./ 필요가 없습니다. 그냥 OBJ = build이면 충분합니다. 위에서 언급 한 바와 같이

  3. 당신은 build/ 필요하지 않습니다. 하지만 그건 중요하지 않습니다. 어쨌든 그것을 언급해서는 안되기 때문입니다. 당신이 그것을 볼 때 build$(OBJ)와 Repece.

  4. mkdir 디렉토리가 이미 존재하면 실패합니다.당신은 아마 -와 해당 명령을 접두사해야한다 : 나는 위의 # 3에서 언급 한 $(OBJ)로 교체 한 적이

    $(OBJ): 
        -mkdir $(OBJ) 
    

    참고.

  5. 자동 생성 의존성은 매우 유용합니다. 표시된 프로젝트가 실제로 필요한만큼 크지는 않지만 추가하기는 쉽지만 이유는 없습니다. 몇 가지 일을해야합니다. 첫째, 적절한 종속 파일 이름을 얻을 :

    DEPFILES = $(addprefix $(OBJ)/,$(SOURCES:.m=.d)) 
    

    을 그 다음 -MMD 플래그를 추가하여를 생성하는 컴파일러를 얻을 :

    gcc -MMD -c $< -o [email protected] 
    

    마지막을 그들이 사용할 수 있다면,에 의해, 당신의 메이크 파일에 포함 당신의 메이크 파일의 끝에 행을 추가 :

    -include $(DEPFILES) 
    
+0

그래서'build /'에 기본적으로'make'를 만들어서 파일을 갱신하고 강제로 재 컴파일하게 만들었습니까? – varesa

+0

그렇게 보입니다. 그것은 내 컴퓨터에서는 발생하지 않지만, 그 동작은 파일 시스템에 의존 할 수 있다고 생각합니다. –

+0

또는 마운트 매개 변수와 관련이있을 수도 있습니다. 주로 타임 스탬프를 업데이트해야 할 때 알려줍니다. – varesa

관련 문제