Makefile 잘 만들기

IDE 환경을 주로 쓰는 사람들은 Makefile을 만들 이유가 없다. Makefile이 해야할 일을 IDE에 내가 일일이 알려주고 있기 때문에 IDE가 알아서 만들어주거나 make가 해야할 일을 대신 해주기 때문이다.

그래도 어쩔 수 없이 Makefile을 만들어야 하는 경우가 있는데, 내 경우는 내가 IDE를 쓸 수 없는 상황이라거나 IDE가 너무 무거워서 그 꼴을 보기 싫은 경우가 대표적이다.

많은 파일들을 한화면에 띄워놓고 편집해서 프로젝트를 만들어야 할 경우에 IDE로 일하는 것 보다 더 빠르고 편리할 수 없다. 많은 IDE가 있지만 요새 많이들 쓴다는 eclipse는 뜨는 것 자체가 무겁고 그 특유의 인터페이스가 싫어서 좋아하지 않는다. 자바로 되어있는 까닭에 플랫폼과 상관없이 쓸 수 있다는 것이 큰 장점이란 것은 인정하지 않을 수 없다만. 안드로이드 스튜디오도 별로 좋아하지 않는다. 비주얼 스튜디오도 마찬가지로 별로 안좋아한다. 솔직히 Xcode 하나만 좋아한다.

내가 10.6.3으로 처음 MacOS를 접해보고 나서 가장 매료되었던 것이 Xcode였기 때문이지 싶은데, 그 이후로 Xcode 말고 다른 IDE는 쳐다보지도 않았고 그게 허락되지 않으면 vi를 쓰든 이름 모를 텍스트 에디터를 쓰면 썼지 eclipse는 최대한 안쓰려고 했다. (내가 아는 사람들 중의 실력자들 중에 여태도 vim을 열심히 쓰는 사람들이 있다. 울트라 에디터를 여태 애용하는 사람들도 있고)

사실 Xcode는 완전한 범용 IDE라고 보긴 어려워서 늘상 그것을 쓰진 않지만 그렇게 좋다. 얘기가 많이 샜는데, 어쨌든 IDE를 쓰지 않으면 IDE에 익숙했거나 IDE로 해놓은 일이 많을 때 불편한 경우가 많다. 그 중에 하나가 Makefile을 쓰는 것이라고 나는 본다.

Makefile은 잘 쓰는 법이 책으로도 있고 웹을 뒤져봐도 많은 아티클들이 나오는데, 딱히 어떤 게 나에게 맞는지 골라골라 찾아내는 게 또 그렇게 쉽진 않다. 결국 어쩌다 Makefile을 써야 할 때마다 조금씩 터득한 기술을 모아모아 나만의 스타일로 만들어 쓰게 된다.

가장 처음 마주하는 문제가 Makefile이란 것은 도대체 어떤 형식으로 쓰여져야 하는 것이다.

gnu project들처럼 그 자체가 덩치가 크고 작은 프로젝트들의 모임으로 구성되는 경우는 그렇지 않지만, 작은 프로젝트들의 경우는 대개 이런 식으로 쓰여져있다.


변수 선언 … …

all: A

A: B 동작 1 (변수 $<, 또는 $@) 동작 2

B: C 동작 1 (변수 $<, 또는 $@) 동작 2

뭐 이런 식이다.

요약하면

콜론 좌측에 놓이는 것이 target이고 우측에 놓이는 것이 depedency라고 보면 된다.

즉, 목표가 되는 대상을 만들기 위해서 동작 1, 2를 수행하는 것인데, 이 때 dependency로 지정된 것들이 있어야 된다는 것이다. 따라서 해당 dependency가 이루어지지 않았다면 그것들을 먼저 처리해주는 식이 되는 것이다.

이것은 쉽게 말해 batch 파일 같은 것을 만들고 싶었는데, 어차피 프로젝트를 빌드하는 과정에서 이루어지는 일들은 단순하다고 볼 수 있으니까 그것을 위해서 최대한 간단한 포멧으로 그 일을 할 수 있게 만든 거라고 봐야 할 것이다. 그것을 배치를 수행해주는 프로세서에 해당하는 make가 실행해주는 것이고.

아래는 그냥 쉽고 흔한 예이다.

SRC = 컴파일하려는 cpp 파일들을 적어놓고 시작하면 아래 내용을 수행하게 된다.


OBJECTS=$(SRCS:.cpp=.o) EXE = zzz

all: $(EXE)

$(EXE): $(OBJECTS) $(CC) $(LDFLAGS) $^ -o $@

%.o: %.cpp $(CC) $(CFLAGS) -c $< -o $@

clean: rm -rf $(OBJECTS) $(EXE)


보는 바와 같이 make를 실행하면 zzz라는 결과물을 만들기 위해서 OBJECT들이 있는지를 보고 그게 없으면 이와 관계된 cpp들을 컴파일해서 빌드를 하겠다는 뜻이 된다.

위의 경우는 cpp 파일에 dependency가 있어서 해당 파일이 변경되거나 하면 선택적으로 컴파일을 하게 한다. 반면 header들이 변경될 때는 그런 일을 하지 않는다. IDE 같으면 전체 프로젝트를 거의 다시 빌드할 정도로 대공사가 일어나는데 말이다.

그것을 위해서 dependency에 header file들을 추가할 수 있다.

생각외로 make도 많은 발전이 있었기 때문에 다양한 기능을 하는 키워드들도 많고 재미있는 기능도 많다. 그런데 모든 언어와 처리기들의 능력이 점점 좋아지다 보니까 그들의 기능 향상이라는 게 중첩되는 게 많아져서 모든 것을 다 잘 알 필요나 이유도 없고 그저 한 가지만 딱 부러지게 잘하는 것이 더 큰 도움이 되는 것 아닐까 한다.

하지만 make는 의외로 마주해야 할 일이 좀 많다. autoconf같은 것도 잘 쓰면 요긴할 때가 많고 cmake도 쓸 줄 알면 도움을 받을 때가 많다. 이를테면 누군가 복잡하게 만들어놓은 것을 내가 손 바줘야 할 때가 있을 때라든가 일을 빨리 해치우고 싶을 때에 이런 작은 지식들은 귀찮은 일을 하느라 쓸데없는 노가다를 최소의 노력으로 해치울 수 있게 해준다.

IDE에만 의존하는 이들이 너무 많다. Makefile이 뭔지 모르는 이들도 있고 batch로 오토메이션 한번 안해본 이들도 많다. 이 좋은 세상에 단순한 작업을 하루 종일 반복해서 하면서 귀중한 업무시간을 채워가는 사람들도 부지기수로 많다. 어차피 이런 거 좀 잘한다고 능력을 인정받을 세상도 아니고 어차피 업무시간만 채우면 된다 하고 단순 반복 작업을 온종일 하고 있는 것 보단 기계에게 일을 시켜놓고 다른 것에 관심가지고 편한 시간을 보내자는게 목표임을 잊지 말자.