2015-01-20 3 views
2

.cpp 파일이 여러 개 포함 된 폴더가 있습니다. A.cpp, B.cpp 및 C.cpp. 그것들은 모두 서로 독립적입니다. A.cpp를 A.o로 컴파일 한 다음 A라는 바이너리 파일을 컴파일 할 수 있습니다. 따라서 B.cpp와 C.cpp가 있습니다.makefile을 사용하여 하나의 폴더에있는 모든 파일을 독립적으로 컴파일하고 업데이트하는 방법

이 모든 파일을 한 번에 컴파일 할 수있는 makefile을 작성하고 싶습니다. 그리고 미래에 D.cpp와 같은 새로운 파일이이 폴더에 저장되면 makefile은 자동으로이 파일을 처리 할 수 ​​있습니다.

나의 현재 파일

CC=g++ 
CFLAGS=-c -Wall 
LDFLAGS= 
SOURCES=$(wildcard *.cpp) 
OBJECTS=$(SOURCES:.cpp=.o) 
EXECUTABLE=$(SOURCES:.cpp=) 

all: $(SOURCES) $(OBJECTS) $(EXECUTABLE) 

$(OBJECTS): $(SOURCES) 
    $(CC) $(CFLAGS) $(@:.o=.cpp) -o [email protected] 

$(EXECUTABLE): $(SOURCES) 
    $(CC) $(LDFLAGS) $(@:=.o) -o [email protected] 

문제는 하나 개의 .cpp 파일이있는 폴더로 변경되거나 추가되면, 다른 모든 파일이 업데이트되고 내가 할 경우 재 컴파일 것입니다이다.

이 문제를 해결하는 방법을 알려주세요.

감사합니다.

답변

3

귀하의 메이크 파일은 모든 소스 파일을 모든 실행 파일 및 모든 오브젝트 파일의 전제 조건으로 나열합니다.

또한 실행 파일의 전제 조건으로 객체 파일을 좋아하지 않습니다 (make가 자동으로 빌드 할 수 없음을 의미).

이는 문제입니다.

이 메이크 파일에는 규칙이 전혀 필요 없다고합니다.

단지

CC=g++ 
CXXFLAGS=-c -Wall 

의 메이크는 make A을 실행할 수 있도록하고 (그것이 필요하지 않기 때문에 그렇게 할 A.o을 구축하지 않지만) A.cpp에서 A를 구축 할 것입니다. 당신이 요구하는 경우에 당신은 당신이 CC 또는 CXXFLAGS을 설정할 필요가 없습니다 (또는 명령 줄에 설정 괜찮다면. A.cpp에서 A를 구축하는 모든

$ mkdir test 
$ cd test 
$ ls 
$ touch A.cpp 
$ make CC=g++ CXXFLAGS='-c -Wall' A 
g++ -c -Wall A.cpp -o A 

을 메이크 필요하지만하지 않습니다 그것은 A.o로 만들 것입니다.

$ make CC=g++ CXXFLAGS='-c -Wall' A.o 
g++ -c -Wall -c -o A.o A.cpp 

하는 포인트 메이크업은 A.o에서 A를 구축하려고합니다. 당신이을 당신이 뭔가를 원하는 수동 그럼에도 불구하고 모든 것을 지정하려면 (힘 .o 건물) 경우

all: $(subst .cpp,,$(wildcard *.cpp)) 

:

$ make CC=g++ CXXFLAGS='-c -Wall' A 
g++ A.o -o A 

는 같은 라인을 필요로하는 모든 실행 파일 구축 make에 대한 지원을 다시 얻으려면 더 좋아. (어느 10.5 Defining and Redefining Pattern Rules4.12 Static Pattern Rules 사용합니다.)

CC=g++ 
CFLAGS=-c -Wall 
LDFLAGS= 
SOURCES=$(wildcard *.cpp) 
OBJECTS=$(SOURCES:.cpp=.o) 
EXECUTABLE=$(SOURCES:.cpp=) 

all: $(EXECUTABLE) 

%.o: %.cpp 
    $(CC) $(CFLAGS) $^ -o [email protected] 

$(EXECUTABLE): % : %.o 
    $(CC) $(LDFLAGS) $^ -o [email protected] 
다음 그들 모두를 구축 할 make을 작성할 수 있습니다

make A을 특정 사람들을 구축 할 수 있습니다.

1

위의 .SUFFIXES: .o .cppall 행에 입력하십시오.

CC=g++ 
CFLAGS=-c -Wall 
LDFLAGS= 
SOURCES=$(wildcard *.cpp) 
OBJECTS=$(SOURCES:.cpp=.o) 
EXECUTABLE=$(SOURCES:.cpp=) 

.SUFFIXES: .o .cpp 

all: $(SOURCES) $(OBJECTS) $(EXECUTABLE) 

$(OBJECTS): $(SOURCES) 
    $(CC) $(CFLAGS) $(@:.o=.cpp) -o [email protected] 

$(EXECUTABLE): $(SOURCES) 
    $(CC) $(LDFLAGS) $(@:=.o) -o [email protected] 

추가

사용 당신은 $ (출처) 또는 $ (OBJECTS) all에 투입 할 필요가 없습니다이

CC=g++ 
CFLAGS=-c -Wall 
LDFLAGS= 
SOURCES=$(wildcard *.cpp) 
OBJECTS=$(SOURCES:.cpp=.o) 
EXECUTABLE=$(SOURCES:.cpp=) 

.SUFFIXES: .o .cpp 

all: $(EXECUTABLE) 

.cpp.o: 
    $(CC) $(CFLAGS) $(@:.o=.cpp) -o [email protected] 

$(EXECUTABLE): $(OBJECTS) 
    $(CC) $(LDFLAGS) $(OBJECTS) -o [email protected] 

. 당신은 약 .SUFFIXES.cpp.o를 들어

DESTINATION: SOURCE

아래는 특히입니다 작성해야합니다. 그것은로 작동합니다 .SOURCE.DESTINATION:

+0

아니요, 문제가 해결되지 않습니다. –

+0

헤더 파일입니까? – mattn

+0

'$ (EXECUTABLE) : $ (SOURCES)'가 여러 단계에서 잘못되었음을 의미합니다. '$ (OBJECTS) : $ (SOURCES)'도 잘못되었습니다. 그리고 그것들이 문제를 일으키고 있습니다. –

1

all: 줄만 변경하고 그 뒤에 오는 줄을 모두 제거하면됩니다. 당신이 .o 파일을 만들 필요가없는 경우

CC=g++ 
CFLAGS=-c -Wall 
LDFLAGS= 
SOURCES=$(wildcard *.cpp) 
OBJECTS=$(SOURCES:.cpp=.o) 
EXECUTABLE=$(SOURCES:.cpp=) 

all: $(OBJECTS) $(EXECUTABLE) 

, 당신은 또한 all:에서 $(OBJECTS)을 제거 할뿐만 아니라 그것을 정의하는 라인 수 있습니다. 이렇게하면 링크 줄에 $(CC)을 다시 정의 할 필요가 없지만 -Wall$(CXXFLAGS)에 추가해야합니다. 당신이 슬픔주는

CXXFLAGS=-Wall 
LDFLAGS= 
SOURCES=$(wildcard *.cpp) 
EXECUTABLE=$(SOURCES:.cpp=) 

all: $(EXECUTABLE) 
+0

이 예제는 'std'make 초기화 파일을 사용할 수있는 경우에만 작동합니다. 그리고 헤더 파일의 변경 사항이나 사용자 헤더 파일이 현재 디렉토리와 다른 디렉토리에있는 경우 제대로 처리하지 못합니다. .PHONY없이 : 모든 줄, 그것은 'all'파일을 만들 수 없다고 불평 할 것입니다. – user3629249

+0

@ user3629249 : 저는 이것이 makefile에 대한 일반적인 해결책이 아니라는 것을 인정합니다. 그것은이 특별한 질문에 관한 것입니다. – jxh

+0

'.PHONY : all'은'all' 파일이 생기면 아무것도하지 못하도록 만듭니다. make는'all' 파일을 만들 수 없다는 에러를 내지 않을 것입니다 ... 적어도'GNU Make 3.81'에서는 새로운 버전이 그 새 니티 체크를 추가 할 가능성이 있습니다. –

1

두 라인은 다음과 같습니다

$(OBJECTS): $(SOURCES) 

$(EXECUTABLE): $(SOURCES) 

첫 번째는 모든 객체 파일이 원본 파일의 모든 일에 따라 달라집니다 "라고, 모든 소스 파일을 변경하는 경우, 모든 객체 파일의 부족 날짜". 두 번째는 실행 파일에 대해서도 마찬가지입니다.

make은 소스 파일에서 직접 실행 파일을 빌드하는 방법을 알고 있습니다. 당신은 중개자로서 목적 파일을 필요로하지 않는다.

나는 all 라인에서 $(OBJECTS)을 제거 하겠지만 (실제로는 오브젝트 파일이 필요하지 않으므로).

그런 다음 내가 지정한 줄과 그 뒤에 오는 명령을 제거 할 수 있습니다 (질문에 표시된 마지막 네 개의 비어 있지 않은 줄을 제거하십시오).

당신은 여전히 ​​모든 오브젝트 파일을 생성 할 수있게하려면

은 추가

objects: $(OBJECTS) 

및 모두를 만들기 위해 make objects를 사용합니다.

FWIW : 개체를 만드는 컴파일 규칙은 -c을 직접 지정하고 $(CFLAGS) 매크로에 포함시키지 않아야합니다. 실행 파일을 빌드하는 컴파일 규칙은 $(CFLAGS) ($(LDFLAGS) 및 아마도 $(LDLIBS)도 가능)을 사용할 수 있습니다.

$(OBJECTS): 
    $(CC) -c $(CFLAGS) $(@:.o=.cpp) -o [email protected] 

$(EXECUTABLE): 
    $(CC) -o [email protected] $(CFLAGS) [email protected] $(LDFLAGS) $(LDLIBS) 

개체 편집 라인의 -o [email protected]은 적어도 필자의 경험으로는 대개 불필요합니다.C 컴파일러는 어쨌든 [email protected]을 생성합니다. 소스가 현재 디렉토리에 있지 않더라도 문제가 될 수 있지만 어쨌든 시나리오가 아닙니다.

일반적으로 내장 규칙을 사용하면 ${@:.o=.cpp}과 같은 비밀 주문을 올바르게 입력하지 않아도됩니다. 대부분의 버전이 make 인 경우 기본 제공 규칙은 내가 설명한 것과 매우 비슷합니다 (make을 사용하여 무엇이 있는지 알아 보려면 make -p을 사용하십시오). 그리고 GNU make에는 %.o: %.cpp 표기법을 사용하는 현대 규칙이 있지만 표시된 코드는이를 가정하지 않습니다.

+0

'-c' 플래그의 위치와'$ (CFLAGS')의 사용에 관한 좋은 참고 사항. 정적 규칙에서'$ *'를 사용하면 (특히 "인식 된 접미사"에 의존하기 때문에) 항상 가드를 잡아 먹게됩니다. –

+0

@EtanReisner : 아마도 당신이 맞을 것 같습니다. 여기서'$ @'를 사용하는 것이 더 낫습니다. –

+0

'$ @. cpp'는 실행 파일에는 작동하지만 오브젝트 파일에는 작동하지 않습니다. 그것은'$ (@ :. o : .cpp)'또는 이와 유사합니다 (당신이 가지고 있지 않기 때문에 필수 변수를 사용할 수 없으므로). 정적 패턴 규칙이 도움이 될 것입니다. –

관련 문제