7. Automatic Dependency Generation

Program Lang./Makefile 2012. 12. 26. 12:57

1. 개요 

 

1장 기본 Makefile 소개 부분에서 각 오브젝트 파일과 관계되는 헤더파일을 일일이 수작업으로 의존관계를 명시하였다.

이런 관계 명시는 예제 수준에서는 가능하나 일반 프로젝트에서는 불가능한 일이다. 일반적으로 프로젝트는 매우 많은

의존 관계로 엮어 있으며, 헤더 파일은 또 다른 헤더 파일을 포함하는 둥 매우 복잡한 구조이다. 

따라서 exam1 예제처럼 일일이 기술하는 것은 의미없는 일이라는 것을 유추할 수 있다.  

 

역사적으로 의존관계 설정에 관해서 몇가지 변화를 거쳤다. 소개하면 다음과 같다.

1) 의존 관계 자동 생성 후, Makefile 하단에 붙이는 방식

 

초창기에는 아래와 같은 문구 아래에 의존관계 내용을 기술하였으나, 좋은 방식은 아니다.  

 

Automatically generated dependecies follow - Do Not Edit 

 

2) 의존관계 생성을 위한 Target 지정하고 빌드 전에 호출하도록 하는 방식

 

1)번에서 매번 수작업으로 붙여야하는 번거로움은 제거하였으나 여전히 빌드전에 의존관계 Target을 수행해야

하는 번거로움이 있다. 학창 시절에 make전에 make depend를 수행했는데 이런 시절에 사용하던 방식인가 보다.  

 

depend: count_words.c counter.c

$(CC) -M $(CFLAGS) $^ > $@

include depend 

 

마지막 방법은 GNU에서 개선한 방법으로 아래에서 설명하도록 하겠다.

 

2. GNU 또는 최신 make에서 의존 관계 생성

 

GNU나 최신 make에서는 위의 두 가지 방식에서의 번거로움을 개선하였다.

일단 각 소스파일에 해당하는 의존 관계 파일을 -M 옵션으로 생성한다. 마지막으로 include 지시자를 통해서

생성된 파일을 추가하여 변경사항에 대해서 자동으로 빌드에 반영하도록 하였다.

 

3. 예제

 

exam4.zip

 

소스와 헤더가 분리된 exam 예제를 가지고 의존관계를 자동으로 생성하여 빌드에 반영하도록 Makefile을

수정하였다. 기존 예제와 변경한 예제간의 차이를 보면 이해할 수 있을 것이다.

일단 의존관계를 생성하는 패턴 룰이 추가적으로 추가되었고 마지막에 include 지시자를 통해서 의존관계

파일을 Makefile에 추가하는 부분이 추가되었다. 컴파일 옵션을 통해서 의존관계에 대한 패턴 룰은 제거할 수 있다.

좀 더 관심 있는 사람은 찾아보고 적용해 보자. (주석처럼 부분 참고)

 

#***********************************************************************#
# ----------------------------------------------------------------------
#  Copyright(c) 2012-2013 by hee-soon kim 
#
# All rights are reserved
# 
# ----------------------------------------------------------------------#
#
#  FILE NAME    : Makefile
#  VERSION      : 1.0
#  AUTHOR       : heesoon,kim(김희순), chipmaker.tistory.com)
#  DATE         : 2012/12/21
#
#***********************************************************************#

obj_dir = obj
include_dir = include

VPATH = src
CFLAGS += -I $(include_dir)

sources = 
sources += bar.c foo.c main.c

objects = $(foreach src,$(sources),$(obj_dir)/$(src:.c=.o))
dependencies = $(foreach src,$(sources),$(obj_dir)/$(src:.c=.d))

all : $(objects) exec

exec : $(objects)
	gcc -o exec $^			# Using Automatic Expanded Variable
	
clean :
	rm -rf $(obj_dir) *.exe
	
$(obj_dir)/%.d : %.c
	echo "Generating Dependencies ..."
	@test -d $(obj_dir) || mkdir -p $(obj_dir)
	$(CC) -M $(CFLAGS) $< > $@.$$$$;						\
	sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; 		\
	rm -rf $@.$$$$

$(obj_dir)/%.o : %.c
	echo "Starting Pattern Rules ..."
	@test -d $(obj_dir) || mkdir -p $(obj_dir)
#	$(CC) -MMD -MF $*.d $(CFLAGS) -o $@ -c $<
	$(CC) $(CFLAGS) -o $@ -c $<	

include $(dependencies)

 

: