2016-07-14 2 views
1

몇 가지 구성을 지원해야하는 C++ 프로젝트의 makefile을 작업하고 있습니다. 예를 들어 디버그, 릴리스 및 향후 몇 가지 사용자 정의 메이크 파일을 만들 수 있습니다.메이크 파일 패턴 규칙 : 원형 makefile.o <- 메이크 파일 의존성이 떨어졌습니다.

현재 생성 된 .o 파일의 이름 지정 규칙은 $(SOURCE_FULLPATH).$(CONFIGURATION).o입니다. 예를 들어 ABC.cpp은 디버그 모드에서 ABC.cpp.debug.o을 생성합니다.

이제 구성에 독립적 인 방식으로 해당 오브젝트 파일을 생성하기위한 패턴 규칙을 작성하고 싶습니다. 내가 한 것은 각 XX.o 파일 이름에서 .debug 또는 .release 접미사를 XX에서 제거하고 나머지 부분 인 XX을 소스 파일 이름으로 사용합니다.

make: Circular makefile.o <- makefile dependency dropped. 

나는 의아해 나는 내가 대상으로 makefile 또는 makefile.o을 나열하거나하지 않기 때문에 : 나는 메이크업에서 하나의 경고 메시지 것을 제외하고이 트릭으로

%.o: $$(basename %) 
    $(CC) $(CC_FLAGS) $(INCLUDE_FOLDERS) -c -o [email protected] $< 

, 나는 제대로 실행 파일을 구축 할 수 있습니다 내 메이크 파일 어디서나 의존성. 나는 SO 검색을했지만, 순환 의존성에 관한 대부분의 질문은 makefile 자체가 아니라 특정 사용자 소스 파일에있다. 순환 의존성의 원인을 이해하는 데 도움을 줄 수있는 사람이 누구이며이 경고 메시지를 제거하는 방법?

이 문제를 재현 할 수있는 샘플 메이크 파일은 다음과 같습니다.

.SECONDEXPANSION: 

PROJECT := helloworld 
CC := clang++ 
BUILD_FOLDER := Build 
OBJ_FILE_SUFFIX := .o 

# Source 
CPP_FILES :=\ 
    Source/hello.cpp \ 
    Source/mysqrt.cpp \ 

INCLUDE_FOLDERS := \ 
    -IInclude 

# MMD outputs the dependency files (".d" files). These files will be used by 
# this makefile to allow for dependency checking on .h files. 
CC_FLAGS += -MMD 

EXISTING_OBJ_FILES = $(wildcard $(addsuffix *.o, $(basename $(CPP_FILES)))) 

##-------------------- 
## Targets definition 
##-------------------- 
.PHONY:default 
default: all 

.PHONY:all 
all: debug release 

.PHONY:debug release 
# Add a 'debug'/'release' suffix to the name of the object file 
# e.g. hello.cpp -> hello.cpp.debug.o 
debug release: OBJ_FILES=$(addsuffix [email protected]$(OBJ_FILE_SUFFIX), $(CPP_FILES)) 
debug release: $${OBJ_FILES} # Use Secondary Expansion to get the obj names 
    $(CC) $^ -o $(BUILD_FOLDER)/$(PROJECT)[email protected] 

# Strip configuration name from the end of the object file name 
%.o: $$(basename %) 
    $(CC) $(CC_FLAGS) $(INCLUDE_FOLDERS) -c -o [email protected] $< 

## clean: remove executable, all object files, and all dependency files 
.PHONY:clean 
clean: 
    -rm -f $(BUILD_FOLDER)/$(PROJECT) $(EXISTING_OBJ_FILES) $(EXISTING_OBJ_FILES:.o=.d) 

# Include the dependent files so that in later builds, modified .h files 
# will cause all .cpp dependent on them to rebuild 
-include $(OBJ_FILES:.o=.d) 

폴더 구조가

makefile 
Source 
- hello.cpp 
- mysqrt.cpp 
Include 
- mysqrt.h 

make debug의 전체 출력

make: Circular makefile.o <- makefile dependency dropped. 
clang++ -MMD -IInclude -c -o Source/hello.cpp.debug.o Source/hello.cpp 
clang++ -MMD -IInclude -c -o Source/mysqrt.cpp.debug.o Source/mysqrt.cpp 
clang++ Source/hello.cpp.debug.o Source/mysqrt.cpp.debug.o -o Build/helloworld_debug 

모두가 첫 번째 행을 제외한 양호하다.

내 메이크 파일에 나쁜 습관이있는 사람이라면 누구든지 나에게 지적 해 주시면 감사하겠습니다. (아직 메이크 파일의 초보자입니다.) 미리 감사드립니다.

답변

2

GNU Make는 항상 을 만들기 전에 읽은 makefile을 업데이트하려고 시도합니다. 에 메이크 파일을 업데이트하라는 규칙과 전제 조건을 발견하면 makefile을 업데이트하는 것을 포함하여 을 다시 시작한 다음 처음부터 다시 시작합니다. 3.5 How Makefiles Are Remade을 참조하십시오. 당신의 조리법에

은 :

%.o: $$(basename %) 
    $(CC) $(CC_FLAGS) $(INCLUDE_FOLDERS) -c -o [email protected] $< 

당신은 makefile에서 makefile.o을 만들기위한 규칙과 make를 제공하고 있습니다.

또한 빌트인 레시피 단일 객체 파일에서 실행한다

%: %.o 
    $(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o [email protected] 

에 규칙의 역이다.그래서 조리법 원형을 발표했다 :

makefile.o <- makefile <- makefile.o 

make이 목표로 자신을 makefile을 고려할 때. 당신은 명시 적으로 빈 규칙을 작성하여 내장 역 규칙, 을 삭제하여 원형을 억제 할 수있다 : 메이크에서
%: %.o 

.

$ make makefile.o 
clang++ -c -o makefile.o makefile 
clang: warning: makefile: 'linker' input unused 

을 그리고 당신은 makefile.o에 을 의존하는 모든 대상을 시도하는 경우 동일한가 발생합니다 : 그럼 당신은 컴파일러의 부분에 다음과 같은 혼란을 관찰 할 수있다.

makefile.o에 의존하는 대상이 없다고 가정하는 것이 안전 할 것입니다. 역시 어떤 파일든지 에서 foo.o를 컴파일하는 것을 시도 할 규칙은 명확하게 당신이 를 원하거나 필요로 한 ㄴ다는 것을 훨씬 청소하고있다. 캡처하고자하는 종속의 특정 패턴 : - 추정되는 규칙 GNU에서 규칙을 확인하는 것이, BTW

%.o: $$(basename $$(basename %)).cpp 
    $(CC) $(CC_FLAGS) $(INCLUDE_FOLDERS) -c -o [email protected] $< 

참고 :

foo.cpp.{debug|release}.o: foo.cpp 

당신은 더 나을 것 by GNU Make의 기본 규칙 - CC은 C 컴파일러를 나타내며 CXX은 C++ 컴파일러를 나타냅니다. 마찬가지로 C 컴파일러의 플래그는 이고 CFLAGS이며 C++ 컴파일러의 플래그는 CXXFLAGS입니다. 전처리 옵션입니다 - - 종래 CPPFLAGS 통과하는 처리기에 대한

플래그 경로를 옵션 을 CPPFLAGS을 표시하고 -I된다.