Make 파일에 대해 그나마 괜찮은 블로그 포스트가 하나 있어 소개합니다. 제목은 Make 대해 알아야 할 7 가지인데, 이것만 보면 makefile을 만들거나 만든거에 대한 이해를 도와줄 수 있을 거 같습니다.
구체적인 내용은 아래와 같습니다.
Make는 다양한 유형의 파일들을 자동 빌드하는데 간단하면서도 강력한 도구이다. 그러나 makefile을 작성할 때 문제가 발생하는 프로그래머들도 있고, Make의 기본 지식이 없어 기존에 있는 것을 다시 만드느라 시간을 낭비하는 프로그래머들도 있다.
1. Make는 어떻게 동작하나?
기본적으로 Make는 첫번째 target에서 시작한다. 이 target을 디폴트 목표(goal)라고 한다.
Make는 현재 디렉토리의 makefile을 읽고 가장 먼저 룰(규칙) 처리를 시작한다. 그러나 Make가 완전히 이 룰(규칙)을 처리하기 전에 룰(규칙)이 종속 파일에 대한 룰을 먼저 처리해야 한다. 각 파일들은 자신의 룰에 따라 처리된다.
사실 이것은 각 target의 재귀 알고리즘으로 되어 있다.
- target을 빌드하는 룰(규칙)을 찾아낼 것이다. 만약 target을 빌드할 룰(규칙)이 없다면, Make는 실패한다.
- target의 전제 조건이 있는 경우 그 전제 조건과 함께 알고리즘이 실행된다.
- target이 존재하지 않거나 전제 조건의 갱신 시간이 target의 갱신 시간보다 이후인 경우 target과 관련된 레시피를 실행한다. 레시피가 실패한다면, (보통) Make도 실패한다.
2. 할당 유형
Make는 makefile을 쓰는 것을 단순화하기 위해 변수가 지원된다. =, ?=, :=, ::=, +=, !=연산자 중 하나를 가지고 할당된다. 각 연산자의 차이점은 다음과 같다.
- =는 지연된 값을 변수에 할당한다. 즉, 변수가 사용될 때마다 변수의 값이 요구된다는 의미이다. 쉘 명령의 결과를 대입할 때 - 변수가 읽혀질 때마다 쉘 명령이 실행된다는 것을 잊지 마시라.
- :=와 ::=는 기본적으로 같은 의미다. 이러한 대입은 변수값을 한 번만 처리하고 그 값을 저장한다. 단순하고 강력하다. 이런 유형의 할당은 디폴트로 선택되어야 한다.
- ?= 는 변수가 정의되지 않은 경우에만 :=역할을 한다. 그렇지 않은 경우는 아무것도 하지 않는다.
- +=는 더하기 대입 연산자이다. 변수가 미리 :=또는 ::=에 설정되어 있는 경우, 우변은 즉시 값으로 간주된다. 그렇지 않으면 지연된 값으로 간주된다.
- !=는 쉘 대입 연산자다. 우변은 즉시 평가되고 쉘에 전달된다. 결과는 좌변의 변수에 저장된다.
3. 패턴 룰
동일한 룰(규칙)을 가진 파일을 많이 가지고 있는 경우 모든 target을 일치시키기 위해 패턴 규칙을 쉡게 정의할 수 있다. 패턴 규칙은 target에 ’%‘가 있는 것을 제외하고는 보통의 룰(규칙)과 비슷하다. 패턴 룰의 타겟은 파일 이름과 일치하는 패턴이라고 판단되며 ’%‘는 공백이 아닌 부분 문자열에 일치시킬 수 있다.
내 블로그 디렉토리에는 다음과 같은 Makefile을 만들 수 있다.
all: \
build/random-advice.html \
build/proactor.html \
build/awesome_skype_fix.html \
build/ide.html \
build/vm.html \
build/make.html \
build/%.html: %.md
Markdown.pl $^ > $@$@가 target을 의미하는 반면, $^의존 관계를 의미하는 자동 변수다. 그래서 이 룰은 단순히 마크다운 파일 변환기에 전달하는 룰이다. 패턴 룰의 작성과 자동 변수에 대한 자세한 내용은 매뉴얼를 참조 하라.
4. 디폴트 묵시적 룰
GNU Make에는 기본 룰(규칙)이 있다. 많은 경우 명시적 룰을 사용할 필요는 없다. 디폴트 묵시적 룰 목록은 C, C++, 어셈블러 프로그램의 컴파일 룰과 그들을 링킹(연결)하는 것을 포함하되 제한은 없다. 전체 목록은 Make 설매뉴얼에서 볼 수 있다.
Makefile에 아무것도 하지 않는 것도 가능하다. 예를 들어, 단순히 hello.c라는 파일에 프로그램 소스 코드를 저장하고 단순히 make hello를 실행할 수도 있다. Make는 hello.c에서 hello.o를 자동으로 컴파일하고 hello에 링킹(연결)한다.
레시피는 $(CC) $(CPPFLAGS) $(CFLAGS) -c형식으로 정의한다. 변수를 변경하여 룰을 바꿀 수 있다. 소스 파일을 clang으로 컴파일하기 위해서는 단순히 CC := clang라인을 추가해주면 된다. 나는 작은 테스트 프로그램을 저장할 디렉토리에 아주 작은 Makefile을 가지고 있다.
CFLAGS := -Wall -Wextra -pedantic -std=c11
CXXFLAGS := -Wall -Wextra -pedantic -std=c++11
