'Program Lang.'에 해당되는 글 72건

  1. 2012.12.26 7. Automatic Dependency Generation
  2. 2012.12.08 2. Wildcard, Phony Target, Empty Target Usage

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)

 

:

2. Wildcard, Phony Target, Empty Target Usage

Program Lang./Makefile 2012. 12. 8. 14:57

1. Wildcard를 이용한 Target, Prerequisite 구성

 

make에서 wildcard (~, *, ?, [...], [^...]) 사용은 Born Shell상에서 사용법과 동일하다. 

 

prog : *.c

$(CC) -o $@ $^                                         # $@ : 현재 Target , $^ : 현재 Prerequisite

 

 

2. Phony Targets

 

일반적으로 Target과 Prerequisite에는 업데이트될 파일에 대한 파일 이름을 기술하였다. 하지만 Phony Target 은

파일 이름이 아닌 단순 라벨(Label)로 기술된다. Phony Target은 파일 이름을 기술하지 않기 때문에 항상 업데이트

되야할 타겟이다. 일반적으로 Prerequisite를 가지지 않는 구조이다.

 

실제 make는 Phony Target과 일반 파일 이름의 타겟을 구분하지 못한다. 이를 구분하기 위해서 make는

Phony Target을 지정하는 지정자 (.PHONY)를 통해서 명시적으로 Phony Target를 지정할 수 있다.  (아래 예제 참조)

 

.PHONY : all clean

clean :

rm -rf *.o *.exe  

 

이미 make에 지정된 표준 Phony Target이 존재한다. 이는 아래와 같다.

 

 

Target 

설명 

 all

 일반적으로 실행파일을 빌드하기 위해 필요한 타겟리스트를 명시한다.

 install

 실행파일을 설치할 목적

 clean

 소스 파일로부터 생성된 바이러리 파일 삭제

 distclean

 소스 이외의 모든 파일 삭제

 TAGS

 테그 생성

 info

 정보 출력

 check

 테스트 목적

 

 

3. Empty Targets

 

위의 Phony Target은 항상 업데이트되어야 타겟이다. 하지만 경우에 따라서는 필요할 때만 업데이트를 원할 때

가 있을 것이다. 이런 요구 사항을 만족하기 위해서 필요한 Target이 Empty Target이다.

예제는 아래와 같고 이런 타겟이 있다라고만 한번 보고 넘어간다.

 

prog : size prog.o

$(CC) $(LDFLAGS) -o $@ $^

size : prog.o                                            # prog.o가 prerequisite로 사용되었다.

size $^

touch size

 

 

: