Make 기반 빌드 시스템 (1): 빌드 시스템?

빌드 시스템?

기본적으로 하나의 프로그램은 수 많은 소스코드들로 이루어져 있고, 규모가 커지면 여러 가지 모듈 또는 라이브러리들로 나누어지게 됩니다. 따라서 작성된 소스 코드로부터 최종 결과물들을 빌드하는데 시간도 많이 걸릴 뿐 아니라, 경우에 따라서는 여러 가지 환경과 옵션에 따라 다르게 빌드할 필요도 생깁니다. 효율적으로 개발하기 위해서는 의존성 관계를 잘 추적해서 그중 일부가 수정되면, 수정된 소스 파일들과, 그 수정으로 인해 변경되어야 하는 소스 파일들만 새로 컴파일 하는 기능도 꼭 필요할 겁니다.

이런 점들을 고려한 통합 개발 환경(Integrated development environment, IDE)은 예전서부터 있어 왔고, 요즘은 정말 훌륭한 툴들이 많이 있습니다. IDE를 사용하면 소스 코드 편집, 빌드, 실행 및 디버깅을 하나의 프로그램 내에서 편리하게 진행할 수 있습니다. 당연히, 의존성에 따라 꼭 필요한 파일들만 다시 빌드 해주는 식으로 빌드 옵션 관리도 똑똑하게 해 줍니다. 심지어는 코드를 수정해서 저장하자 마자, 백그라운드로 빌드해 주기도 하죠.

하지만, 어떤 경우에는 적절한 IDE가 없을 수도 있고, 경우에 따라서는, 예를 들어 일일 자동 빌드를 하는 경우에는, IDE가 오히려 불편할 수 있습니다. 그래서 좋은 개발 도구들은 GUI 기반의 IDE와 함께, 도스나 터미널 같은데서 명령어 기반으로 빌드할 수 있는 기능을 같이 제공하더군요.

그러나 어떤 이유에서였든, GUI 기반의 IDE 없이 개발해야 한다면, 그럼 도대체 어떻게 그런 똑똑하고 효율적인 빌드를 수행할 수 있을까요… 불행히도 없습니다… (응?) 농담입니다. 다행히도, 그런 운 나쁜(?) 개발자들이 의지할 수 있는 친구들이 몇 있는데요, 그 중 하나가 make입니다.

make는 주어진 규칙에 따라 작성된 입력 파일의 내용에 따라 주어진 일을 자동으로 수행하는 유틸리티입니다. 사실 make를 이용해서 여러 가지 작업들을 할 수 있겠습니다만, 소프트웨어 개발자 입장에서 보면 소스 코드를 컴파일하고 링킹해서 최종 결과물을 만드는데 없어서는 안 되는 도구입니다.

참고로 GNU make는 GNU에서 구현한 make이고요, 일반적인 리눅스에는 기본으로 포함되어 있거나 적어도 쉽게 무료로 설치할 수 있습니다. gmake라고도 하죠. 유닉스나 BSD나 기타 다른 OS에서는 gnu make와 다른 make가 있을 수 있는데요, GNU make는 다른 make들에 비해 대부분의 기능 면에서는 문제없이 호환되지만, 자체 확장 기능도 가지고 있습니다. 제 글에서는, 리눅스에서 GNU make를 사용하는 것을 전제로 하기 때문에, GNU make를 그냥 make라고 통칭하도록 하겠습니다.

make에 관련된 가장 훌륭한 레퍼런스는 당연히(?) GNU 사이트의 make 문서입니다.

  • http://www.gnu.org/software/make/manual/make.html: Makefile을 수정하다가, 뭔가 추가로 이런 기능이 있지 않을까? 또는 다른 사람이 작성한 Makefile을 참고하는데 이 내용은 도대체 뭘까? 하는 의문이 들때 결국 찾게 되는 사이트입니다. (단, 영어 실력이 좀 받춰줘야 합니다.)
  • 위 Make 매뉴얼 한글판은 http://www.viper.pe.kr/docs/make-ko/make-ko_toc.html 에 있습니다. (Taehun Kim 님께서 알려 주셨습니다. 아무래도 영어가 부담스러운 사람에게, 위 make 매뉴얼 페이지의 빠르게 내용을 파악하는데 큰 도움이 될 수 있겠네요.

앞으로 쓰는 글에서도 나름 설명하겠지만, make의 기본을 좀 속성(?!)으로 이해하려면, 다음 사이트들의 내용이 큰 도움이 됩니다. 고맙게도 한글로 잘 정리되어 있습니다.

리눅스 쪽 개발 작업에서는 많은 경우 make를 사용합니다. 그리고 생산성과 품질을 중요시하는 제대로 된 개발팀이라면, 다음과 같은 작업이 가능한 빌드 시스템 및 Makefile 파일을 작성하는 고유의 규칙을 가지고 있을 겁니다.

  • 하나의 소스 트리에서 여러 가지 타겟 플랫폼들을 단일 명령으로 빌드할 수 있고,
  • 특정 타겟 별로, 그리고 각 모듈 별로 필요한 빌드 옵션을 적용할 수도 있고, 모든 플랫폼과 모듈들에 동일한 옵션을 한번에 적용할 수도 있으며,
  • 나아가 최종 실행 라이브러리들과 실행파일들을 한방에, 즉 명령어 하나의 입력이나 단축키 하나 누르는 걸로 만들어 내고, 자동화된 단위 테스트(unit test)들을 실행해 낼 수 있습니다.

하지만 늘 해야할 일에 비해 개발인력은 부족한 개발팀에서, 이런 환경을 갖추기란 쉽지 않습니다. 특히나 (제가 주로 몸 담아온 회사들처럼) 규모가 작은 중소기업이라면, 그리고 개발하는 소프트웨어 그 자체로, 돈을 벌어주는 최종 제품이 되는 것이 아니라, 어떤 HW 제품에 내장되는 경우(이를 임베디드 시스템이라 하지요)라면 더더욱 그렇습니다.

일반적으로 뭔가 새 라이브러리나 실행 프로그램을 만들어야 한다면, 그래서 이를 위한 Makefile을 하나 작성해야 한다면, 기존에 존재하는 모듈들의 Makefile 중에서 내가 하려는 것에 가장 비슷한 걸 하나 복사한 다음, 최소한의 수정만 가해서 빌드하는 게 가장 빠르긴 합니다. 하지만 시간이 흐르면서, 모듈들이 많아지고, 요구 조건은 많이 변경됩니다. 하나 둘 컴파일 옵션 추가하는 일도 빈번해집니다. 그때마다 복사해서 사용하던 모든 Makefile들을 똑같이 고치는 단순 반복 노가다를 해야 합니다. 그중의 일부가 누락되면 컴파일 에러가 발생하거나, 운 나쁘면 런타임 에러가 발생합니다. 네, 소스 코드를 복사해서 사용하는 것과 똑같은, 아니 더 심각한 문제가 생기는 거죠.

좋은 환경이 주어지지 않은 걸 한탄만 한다고 달라지지는 건 없습니다. 뭔가 문제가 있다는 인식을 하고 그것을 꼭 해결하겠다는 의지만 있다면, 적어도 효율적인 소프트웨어 빌드 시스템은 만들어 낼 수 있습니다. 이 글은 그런 과정에서의 시행착오를 줄여서 생산적인 개발 작업에 좀더 집중할 수 있게 하고, 소프트웨어 개발자의 삶이 조금이나마 편해지는데 도움이 되었으면 하는 바람에서 쓰여 졌습니다.

사실 요즘은 좋은 빌드 툴들이 여럿 있습니다. 제 개인적으로는 jam 이나 waf 같은 것들을 고민해 봤던 경험이 있습니다. 특히 waf는 제가 좋아하는 python을 이용한 시스템이어서 참 매력적이었지만, 여러 명이 사용해야 하는 환경에서는, 관련된 사람들이 얼마나 쉽게 사용할 수 있어야 하느냐도 무척 중요합니다. 빌드 시스템을 관리하기 위해 새 언어를 배워야 한다라는 걸, 아주 바쁜(!) 여러 사람들한테 설득한다는 것은, 음… 쉽지 않은 일입니다.

그에 비해 Makefile을 작성해서 make로 빌드하는 건, 많은 개발자들, 특히 중요한 역할을 담당하는 경험 많은 개발자들일수록 익숙해져 있기 때문에, 빌드 시스템 구축 및 도입을 비교적 용이하게 할 수 있는 장점이 있습니다. 물론 make도 많은 기능을 가지고 있어서, 어느 정도 쓸 수 있기까지 시간과 노력이 좀 필요하지만, 일단 익숙해지고 나면 개발 과정에서 생기는 여러 가지 돌발 상황을 효과적으로 대응할 수 있습니다. 또한 개발을 진행하다 보면, 이런 저런 이유로 개발팀 외부의 소스 코드나 라이브러리를 활용해야 하는데, 많은 경우 Makefile이 제공되어 make를 이용해서 빌드하도록 되어 있기 때문에, 소프트웨어 개발자로 살아가는데 make를 잘 아는게 언젠가는 도움이 될 겁니다.

이제 그럼 make를 이용해서, “생산성과 품질을 중요시하는데 도움이 되는” 빌드 시스템을 실제로 만들어 보도록 하겠습니다.

 

이 글과 관련된 글 목록:

This entry was posted in 소프트웨어 and tagged , , , , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.