Make:Dependency
Make의 의존관계 생성에 대한 내용을 정리한다.
자동 의존관계 생성
make 을 사용하는 가장 큰 이유는 어떤 파일이 수정되었을 때 Makefile 에 나타난 규칙에 의거하여 그것에 의존하는, 즉 그 수정된 파일로부터 생성되는 파일들을 자동으로 다시 생성해 주기 때문이다. 문제는 이 Makefile 이라는 것이 정확하게 작성되어 있느냐 하는 것이다. 엉성하게 Makefile 을 작성하면 파일들 간의 의존 관계가 정확하게 모두 기술되어 있지 않기 때문에 일부 파일을 수정하고 make 를 해도 실패하거나, 성공한다 해도 잘못된 결과를 얻게 될 가능성이 크다. 따라서 엉성하게 Makefile 을 작성해 놓으면 불안한 나머지 자주 전체 프로젝트를 몽땅 다시 컴파일하고 만다. 하지만 실제로 어느 정도 이상 큰 프로그램에서는 수동으로 정확한 의존관계를 표시하는 Makefile 을 작성하기란 매우 어렵다. 파일들이 한 단계의 의존성이 있는 것이 아나라 여러 단계에 걸쳐 의존성이 생기기 때문이다.
따라서 대부분의 유닉스 환경에서 돌아가는 컴파일러에서는 소스 파일을 컴파일할 때 필요한 다른 소스 파일의 정보를 출력해 주는 기능이 내장되어 있으며, 이들은 보통 Makefile 그대로 입력했을 때 곧바로 사용할 수 있는 형식이다. (gcc 의 경우 -M 으로 시작하는 옵션들이 이에 해당한다.) 또한 그러한 컴파일러 출력을 make 와 곧바로 연동할 수 있도록 하는 gccmakedep, makedepend, mkdep 등의 유틸리티들이 있다. 하지만 이 전통적인 유틸리티들은 어떤 특정 프로젝트의 일부로서 개발되었기 때문에, 컴파일러에 별도의 옵션을 지정한다든지 하는 유연성이 떨어진다. 또한 이들은 공통적으로 하나의 파일로 의존관계를 생성한다는 단점이 있다. 따라서 파일을 하나만 수정해도 같은 디렉토리 안의 전체 소스에 파일에 대한 의존관계를 다시 작성해야 하며 이는 컴퓨터 실행 시간 측면에서도 비효율적이며, 매번 명령 프롬프트에서 명령을 내려야 하므로 번거롭다. 그러므로 매뉴얼 4.14 Generating Prerequisites Automatically 에도 나오듯이, 다음과 같이 패턴 규칙을 이용하여 직접 각각의 파일에 대한 의존관계 파일을 생성할 것을 추천하고 있다.
%.d: %.c
$(SHELL) -ec '$(CC) -M $(CPPFLAGS) $< \
| sed '\''s/\($*\)\.o[ :]*/\1.o $@ : /g'\'' > $@; \
[ -s $@ ] || rm -f $@'
gccmakedep
자동 의존성 생성은 gccmakedep을 사용하면 된다. gccmakedep는 어떤 파일의 의존 관계를 조사하여 Makefile 뒷부분에 자동으로 붙여 주는 유틸리티이다.
Auto-Dependency Generation
참조 사이트에 나와있는 내용을 그대로 사용하지 않고, 프로젝트 성격에 맞춰, 정확히 sed스크립트를 사용해야 한다.
만약, src/main.cpp
파일을 사용하여 src/main.d
파일을 작성할 경우 아래와 같이 적용해야 한다.
CC=gcc
CXX=g++
SED=sed
TEMP_EXTENSION=.tmp
define MAKE_DEPENDENCY
$($(1)) -MM $< $(CPPFLAGS) $($(1)FLAGS) > $@$(TEMP_EXTENSION)
@$(SED) -e 's;^.*\.o: ;$(subst .d,.o,$@) $(subst .d,_g.o,$@) $@: ;g' < $@$(TEMP_EXTENSION) > $@
@rm -f $@$(TEMP_EXTENSION)
endef
MAKE_DEPENDENCY_CC=$(call MAKE_DEPENDENCY,CC)
MAKE_DEPENDENCY_CXX=$(call MAKE_DEPENDENCY,CXX)
...
%.d: %.cpp
$(MAKE_DEPENDENCY_CXX)
-include $(DEPS)
...
위와 같이 작성하는 이유는 gcc -MM
을 적용했을 경우 아래와 같이 디렉터리 경로를 제외한 Target이 적용된다.
따라서 이 타겟을 경로를 포함한, .o
파일, _g.o
파일, .d
파일 Target으로 확장해야 한다.
See also
- Make
- gccmakedep
Favorite site
References
-
Gnu-software-make.zip ↩