Makefile이 두렵다고요? 걱정 마세요!
출처: Illustration by Anindyanfitri - Freepik.com
지난 몇 년간 뛰어난 소프트웨어 엔지니어들과 함께 일할 기회가 있었습니다. 인상 깊었던 점은 그중 많은 분이 Makefiles에 대한 실질적인 지식이 없고, 왜 유용한지도 잘 모른다는 것이었습니다.
빌드 과정을 자동화해야 할 때면 직접 셸 스크립트를 만들곤 합니다. 프로젝트 폴더에 있는 build.sh, run.sh 혹은 doall.sh 같은 파일들이 대표적인 예입니다.
이 스크립트들은 매번 똑같은 기본 기능들을 반복해서 구현합니다:
- 입력 파라미터와 환경 변수 파싱.
- 빌드 단계 간의 의존성 수동 관리.
- 오류 처리(…운이 좋다면).
그러다 보면 매번 같은 실수를 반복하게 됩니다:
- 입력 파라미터와 환경 변수를 잘못 다루는 경우.
- 빌드 단계 간의 의존성을 빠뜨리는 경우.
- 오류 처리를 잊은 채 — 심지어 더 나쁜 경우에는 — 프로그램 실행을 그대로 이어가는 경우.
바로 이런 문제를 해결하기 위해 Makefile이 만들어졌습니다.
Makefile은 무섭다!
make가 무섭다고 생각하신다면, 아마 대규모 소프트웨어 프로젝트의 복잡한 빌드 시스템을 떠올리고 계실 겁니다. 꼭 그렇게 복잡할 필요는 없습니다. make의 창시자인 Stuart Feldman의 말을 직접 들어보겠습니다:
시작은 정교한 의존성 분석기라는 거창한 아이디어였지만, 훨씬 단순한 것으로 축소되었고, 그 주말에 Make가 탄생했습니다. 아직 덜 다듬어진 도구를 사용하는 것은 당시 문화의 일부였습니다. Makefile은 마법처럼 인코딩된 바이너리가 아니라 텍스트 파일이었습니다. 그것이 유닉스 철학이었기 때문입니다. 출력 가능하고, 디버깅 가능하며, 이해할 수 있는 것.
Make는 반복되는 문제를 간단하게 해결하기 위해 단 한 주말 만에 만들어졌습니다.
Makefile은 간단합니다!
외출하기 전에 옷을 입어야 합니다. 저는 매번 같은 단순한 순서로 옷을 입습니다. 속옷, 바지, 셔츠, 풀오버, 양말, 신발, 재킷 순입니다. 아마 여러분도 각자만의 순서가 있을 겁니다. 제 순서와는 조금 다르더라도 말이죠.
이 중 일부 단계는 서로 의존 관계에 있습니다.Make는 이런 의존성을 처리하는 데 유용합니다.
제 일상을 Makefile로 표현해 보겠습니다.
dress: trousers shoes jacket
@echo "All done. Let's go outside!"
jacket: pullover
@echo "Putting on jacket."
pullover: shirt
@echo "Putting on pullover."
shirt:
@echo "Putting on shirt."
trousers: underpants
@echo "Putting on trousers."
underpants:
@echo "Putting on underpants."
shoes: socks
@echo "Putting on shoes."
socks: pullover
@echo "Putting on socks."이 Makefile을 실행하면 다음과 같은 결과가 나옵니다:
$ make dress
Putting on underpants.
Putting on trousers.
Putting on shirt.
Putting on pullover.
Putting on socks.
Putting on shoes.
Putting on jacket.
All done. Let's go outside!무슨 일이 일어난 걸까요?
단계들이 올바른 순서로 실행된 것을 눈치채셨나요? 단계 간의 의존성을 그저 명시해 주기만 하면, make가 올바른 순서로 실행되도록 도와줍니다.
각 빌드 단계는 다음과 같은 구조를 가집니다:
target: [dependencies]
<shell command to execute>
<shell command to execute>
...Makefile에서 첫 번째 타깃은make를 호출했을 때 기본으로 실행됩니다.타깃의 순서는 중요하지 않습니다.
셸 명령은 반드시 탭으로 들여써야 합니다.
실행되는 명령의 출력을 숨기려면 앞에
@기호를 붙이세요.target이 빌드하려는 파일이 아니라면 빌드 단계 끝에.PHONY <target>을 추가해 주세요. 대표적인 phony 타깃은 clean, install, run 등입니다. 그렇지 않으면 누군가install이라는 디렉터리를 만들었을 때, 빌드 타깃이 이미 존재하므로make가 조용히 실패하게 됩니다..PHONY: install install: npm install
축하합니다! make에 대해 알아야 할 내용의 90%를 배우셨습니다.
다음 단계
실제 Makefiles는 훨씬 더 많은 일을 할 수 있습니다! 전체를 다시 빌드하는 대신 변경된 파일만 빌드하고, 가능한 한 많은 작업을 병렬로 처리합니다. 다만, 가급적 단순하게 유지해 주세요.
글을 무작위로 읽기