make를 무지무지 싫어했다. 알수없는 매크로로 덕지덕지 붙어 있는것도 그렇고 탭들여쓰기도 그렇고.. 그런데 그간 내가 make에 대해 오해하고 있었나보다. 나는 make를 ‘변경에 관한 관리툴’로 보지 않고 스크립트언어의 일종으로 본것이다.
make는 빌드 관리 시스템이다. 빌드 관리에서 가장중요한것은 변경에한 관리다. 종속성관리라는 요소도 사실은 변경사항을 적용하기위한 하나의 부가적인 측면에 지나지 않는다. 그래서 make는 변경사항 감시와 변경에 대해, 종속적인 순서에 의거 정해진 일을 해주는 시스템툴이라고 요약할수 있겠다.
make의 기본적인 항목들을 살펴보면 다음과 같다.
1. 매크로 정의
매크로는 다음과 같이 정의할 수 있다.
#재귀적 확장 매크로, 뒤에서 $(VALUE)를 통해 재작성하면 그것도 여기에 적용된다.
VALUE = something
#단순확장 매크로, 이후의 $(VALUE)를 단순히 something으로 치환한다.
VALUE := something
#기존의 매크로에 something을 공백을 두고 덧붙있다.
#ex. 기존 VALUE가 anything 이었다면, 이후 anything something 이 된다.
VALUE += something
#앞에 VALUE가 정의 되어 있지 않다면 VALUE를 정의하고 값을 something이 되게 한다.
VALUE ?= someting
#make 함수를 사용하였다면 그 결과로 치환된다.
VALUE = ($shell pwd)
# 그리고 다음과 같이 사용한다.
all:
#반드시 탭
@echo $(VALUE)
2. 타겟의 기술
타겟은 아래와 같이 기술된다.
target : dependency1 dependency2
<tab>command
타겟은 종속적인것을 먼저 수행하고 타겟의 커맨드를 수행한다. 만일 이때 타겟과 종속적인것이 오브젝트 파일이나 소스파일이라면, 변경사항을 검사하고 확장자 규칙에 자동적으로 종속작업을 할수 있다.
3. 구문 / 함수
make는 여러함수와 간단한 구문을 포함한다. 조건 구문을 먼저 살피면
#아래의 구문은 명령에 들어가며 매크로의 값을 비교해서 명령을 수행한다.
all :
ifeq( &(CC), gcc )
@echo "Complier - GCC"
else
@echo "Complier - Not GCC"
endif
#아래의 구문은 매크로 정의에 따라 타겟을 구성하거나 구성하지 않는다.
ifndef DEF_ONLY_ONE_FILE
#SRCS:.c = .o는 SRCS의 .c 부분을 .o로 바꾸는 make 함수이다
$(TARGET).o : $(SRCS:.c = .o)
# $@은 타켓을 의미하며 $^은 종속성을 의미하는 내부지정 매크로다.
$(LD) -r $^ -o $@
endif
그리고 make는 매크로(문자변수 정도로 생각하면 편할듯)를 편리하게 다룰수 있는 많은 함수들도 제공한다.
#shell함수, 함수뒤에 오는 쉘 명령을 수행하고 결과를 문자열로 던저준다.
PWD := $(shell pwd)
#wildcard 함수, 지정된 디렉토리에서 패턴과 일치하는 파일리스트를 뽑는다.
#디렉토리를 특별히 지정하지 않으면 .와 같다.
#patsubst, $(매크로명:패턴 = 치환할 문자열
SRCS = $(wildcard *.c) #$(wildcard ./*.c와 같다)
OBJECTS = $(SRCS:.c = .o)
#foreach 함수 : $(foreach 변수명, 대입문자열, 확장문자일)
#아래는 현재 디렉토리에서 시작해서
#dir_sub_1과 dir_sub_2 아래에 있는 모든 .c 파일을 SRCS로 만든다.
#먼저 dir이라는 변수명에 . 이 들어가서 $(wildcard ./*.c)가 수행된다.
#만일 현재에 a.c 가 있고 dir_sub_1에 b.c 가 있고 dir_sub_2에 c.c가 있다면
#SRCS 는 ./a.c dir_sub_1/b.c dir_sub_2/c.c 가 있다.
SRCS := $(foreach dir, . dir_sub_1 dir_sub_2, $(wildcard $(dir)/*.c) )
4. 기타 규칙
make의 다른 규칙들을 살펴보려면 ‘make -p’ 명령을 통해 현재 규칙들을 살펴볼 수 있다. 만일 이 명령을 수행한 디렉토리 내에 makefile이 있다면 그 makefile에 대한 매크로와 규칙들을 화면에 출력해줄 것이다.
5. make의 친구들
사실 make는 변경사항을 종속성에 따라 감시하는것을 제외하고는 스크립트로써 꽝이다. (100줄만 넘어가도 정말 내가 뭘 짜고 있는지 모르겠다.) 그런 사람들이 많았는지 makefile 작성을 도와주는 많은 유틸리티 프로그램이 있다. 그중에서 대표적인것이 autoconf와 automake 인데, autoconf는 configure.ac 와 Makefile.in을 가지고 configure 스크립트파일을 만들어 내고 사용자는 이 configure 스크립트 파일을 이용해서 makefile을 생성해 내도록 하는 도구이다. automake는 Makefile.in을 쉽게 만들수 있도록 도와주는 유틸리티다. 사실 이 도구들은 사용하기 조금 까다로와서 KDE같은 경우에는 cmake를 사용하게 전환했다는 소리를 들었다. 음… 요는 makefile을 만들면 되는것 아닌가? 그렇다면 ruby같은 스크립트를 이용하는것도 괜찮을 것이다. 사실 KDevelop을 사용하면 이런 configure.ac 파일같은것들을 쉽게 작성할수 있도록 도와주기때문에 그럭저럭 괜찮고, 또 configure 스크립트가 거의 표준이기때문에 쉽게 떨쳐 내지는 못하겠지만…