목차
make에 대해
Ninja와 Meson에 대해 간단히 알아보자!
1. Make란?
Make는 빌드 시스템입니다.
빌드를 사용자가 gcc같은 명령어를 직접 입력하는 게 아니라,
Makefile에 규칙을 작성하면 make가 알아서 빌드하게 해 줍니다.
1) Make가 없던 시절...
사용자가 컴파일러와 링커 등의 커맨드를 직접 입력하는 건 매우 번거롭습니다.
매번 사람이 직접 할 수는 없으니 자동화를 해야겠죠?
find . -name "*.c" | xargs -I {} gcc -c -o {}.o {}
find . -name "*.o" | xargs | xargs gcc -o main.exe
Shell
복사
현재 디렉터리 내의 모든 c 파일을 컴파일 & 링킹하는 간단한 쉘 스크립트
하지만 이 스크립트로는 매번 모든 c 파일을 컴파일합니다.
소스 파일 10000개 중에 하나만 수정해도 전체를 다시 컴파일합니다!
2) Make가 해결하는 것
의존성 관리를 통해 수정된 것만 다시 빌드합니다.
SOURCE_FILES := $(shell find . -name "*.c")
main.exe: $(SOURCE_FILES:=.o)
gcc -o $@ $^
%.o: %
gcc -o $@ $<
Makefile
복사
현재 디렉터리 내의 모든 c 파일을 컴파일 & 링킹하는 초간단 Makefile
Make가 무엇을 해결하는지만 간단히 알아보고, 자세한 내용은 다루지 않겠습니다.
main.c가 있을 때 make main.exe 명령을 통해 make가 하는 일은 대략 아래와 같습니다.
간단하죠?
Implict Rules
이 과정을 더 자세히 보려면 make -d 옵션을 통해 디버그 로그를 출력할 수 있습니다.
그런데 이 간단한 Makefile의 디버그 로그가 무려 150줄이네요? 그 내용을 조금만 보죠
Considering target file 'main.exe'.
File 'main.exe' does not exist.
Considering target file 'main.c.o'.
File 'main.c.o' does not exist.
Looking for an implicit rule for 'main.c.o'.
Trying pattern rule with stem 'main.c'.
Trying implicit prerequisite 'main.c'.
Found an implicit rule for 'main.c.o'.
Considering target file 'main.c'.
Looking for an implicit rule for 'main.c'.
Trying pattern rule with stem 'main'.
Trying implicit prerequisite 'main.y'.
Trying pattern rule with stem 'main'.
Trying implicit prerequisite 'main.l'.
Makefile
복사
위의 초간단 Makefile에 대한 make -d 출력 중 극히 일부
도대체... 저 간단한 Makefile에서 도대체 무슨 일이 일어나고 있는 걸까요??
Make는 여러가지의 implict rule들이 내장되어 있습니다.
Implict rule을 사용하면 이런 것도 가능합니다.
Implict rule을 모르는 상태로 Makefile을 작성하면 의도대로 동작하지 않을 수도 있지만,
제대로 활용한다면 Makefile을 정말 간단하게 작성할 수 있을 것입니다.
쉘 사용
Make는 명령어를 쉘을 통해 실행합니다.
.PHONY: clean
clean:
[ ! -f $(BUILD_DIR) ] || $(MAKE) -C $(BUILD_DIR) $@
Makefile
복사
쉘을 통해 실행하기 때문에 쉘 스크립트처럼 사용할 수 있습니다. 이건 그 예시!
그리고 명령어를 실행할 쉘로 기본 쉘이 아닌 다른 쉘을 지정할 수도 있습니다.
Makefile을 기능이 추가된 쉘 스크립트처럼 작성한다면 Make로 정말 많은 일을 할 수 있습니다!
2. 요즘의 Makefile은...?
프로젝트를 진행하면서 Makefile을 직접 작성하다 보면 불편한 부분이 많이 있을텐데요,
그래서 CMake나 Autotools 등이 등장했습니다! 많은 프로젝트에서 이런 툴을 사용하고 있습니다.
요즘은 주로 Makefile을 직접 작성하기보다는 다른 툴로 생성된 Makefile을 사용합니다.
Makefile을 생성하는 데 쓰이는 툴을 몇 가지 정말 간단하게 알아보겠습니다.
1) Autotools
Makefile을 직접 작성하는 것이 아닌, Makefile을 만들기 위한 다른 파일을 작성합니다.
그 파일들로 Makefile을 만드는 툴로, Automake와 Autoconf 등이 포함되어 있습니다.
2) CMake
CMake는 Make 뿐 아니라 다른 빌드 시스템도 지원합니다.
Make는 물론이고, MSBuild도 지원하기 때문에 Visual Studio에서도 사용할 수 있습니다.
3. Make의 문제점
Make에는 여러가지 문제점이 있습니다.
1) 너무 무거워요
쉘을 사용합니다. 장점이자 단점인데, Makefile 문법만이 아니라 쉘도 알아야 하는 것이죠.
Implict Rule로 인해 의도치 않은 결과를 얻을 수 있습니다.
잘 쓴다고 해도, Implict Rule을 잘 모르는 사람이 그 Makefile을 읽기는 어려울 것입니다.
파일명에 띄어쓰기가 들어가면 정말 곤란해집니다. 물론 파일명에 띄어쓰기를 안 쓰면 됩니다.
Autotools나 CMake 등을 사용한다면, 다른 툴에서 생성된 파일 주제에 너무 많은 일을 할 수 있죠.
2) 느려요
그 외에도 여러가지 이유로 아무튼 Make는 충분히 빠르지 않아요.
4. Ninja
Make는 꽤 고수준의 빌드 시스템입니다. Makefile은 사람이 직접 작성하라고 있는 것이죠.
Ninja는 속도에 집중한 저수준의 빌드 시스템입니다.
사람이 직접 작성하거나 보라고 있는 것이 아니지만, 대신에 속도가 빠릅니다.
어차피 요즘은 주로 Makefile을 사람이 직접 작성하지 않기 때문에 단점이 되지는 않겠죠?
CMake 역시 Ninja를 지원하기 때문에 CMake를 사용한다면 Ninja 사용을 고려할 만 합니다.
5. Meson
Meson은 Ninja를 사용하는, 빠르고 쉬운 빌드 시스템입니다.
Ninja와 Meson 모두 파이썬으로 만들어졌으며, pip을 통해 설치할 수 있습니다.
Ninja를 사용한다면, 그리고 CMake를 쓰고 싶은 게 아니라면, Meson 사용을 고려할 만 합니다.
혹시 여러분도 Makefile로 고통받고 계시다면... Ninja와 Meson을 시도해 보세요!
그리고 후기 좀 알려주세요