🏷️Makefile
- Makefile의 구조와 기본 동작에 대해 설명한다.
📌Makefile 구조
매크로명 = 값
타켓 : 종속 항목 리스트
<TAB> 명령어1
<TAB> 명령어2
- 명령어 앞은 반드시 다른 공백문자가 아닌
TAB
이어야 한다.
- 타겟을 만들기 위해선, 종속 항목들이 존재해야 한다.
- 종속 항목들이 모두 충족됐을 때, 타겟을 만들어 내기 위해서 아래 기술된 명령어들을 수행하게 된다.
- 주로
gcc
같은 컴파일 관련 명령어들이 사용된다.
- 타겟과 종속 항목은 통상 파일명이 되지만, 반드시 그럴 필요는 없다.
- 🖇️cf. 파일명이 아닌, 개념적인 타겟인 Dummy target이나 특수 타겟이 존재한다. (나중에 상세히 설명)
📌make의 기본 동작
- 예시를 통해 make의 기본적인 동작 방식을 알아보자.
현재 디렉터리에 존재하는 파일들
- 앞으로 Makefile을 작성할 땐, 아래 파일들이 존재하는 작업 디렉터리라고 가정한다.
- 현재 디렉터리에 다음과 같은 3개의 C 소스 파일(
main.c
, add.c
, sub.c
)과 1개의 헤더파일(calc.h
)이 존재한다.
calc.h
#include <stdio.h>
int add();
int sub();
- calc 헤더 파일엔, add와 sub 함수의 비원형 선언이 들어있다.
main.c
#include "calc.h"
int main()
{
add();
sub();
return 0;
}
add.c
#include "calc.h"
int add()
{
printf("function add is called.");
return 0;
}
sub.c
#include "calc.h"
int sub()
{
printf("function sub is called.");
return 0;
}
Makefile
all : calc
calc : add.o sub.o main.o
gcc -W -Wall -o calc add.o sub.o main.o
add.o : add.c
gcc -W -Wall -c -o add.o add.c
sub.o : sub.c
gcc -W -Wall -c -o sub.o sub.c
main.o : main.c
gcc -W -Wall -c -o main.o main.c
- gcc의
-c
옵션은 오브젝트 모듈까지만 생성하도록 한다.
동작 방법
make
명령을 내리면, make는 현재 디렉터리에서 Makefile을 찾는다.
- Makefile 내에 맨 위에 오는 타겟인
all
을 발견한다.
all : calc
all
타겟을 만들기 위한 종속 항목인 clac
를 확인한다.
- 종속 항목인
calc
가 현재 디렉터리에 없다는 것을 확인한다.
calc
를 생성하기 위한 rule(규칙)을 찾는다.
calc
타겟을 발견한다.
calc : add.o sub.o main.o
calc
를 생성하기 위한 첫 번째 종속 항목 add.o
가 현재 디렉터리에 없다는 것을 확인한다.
add.o
를 생성하기 위한 rule을 찾는다.
add.o
타겟을 발견한다.
add.o : add.c
gcc -W -Wall -c -o add.o add.c
add.o
을 생성하기 위한 종속 항목인 add.c
가 현재 디렉터리에 존재한다.
- 따라서 아래의 명령어
gcc -W -Wall -c -o add.o add.c
를 수행해서 add.o
를 생성한다.
- 다시 calc을 생성하기 위한 rule로 돌아간다.
calc : add.o sub.o main.o
- 두 번째 종속 항목
sub.o
가 현재 디렉터리에 없다는 것을 확인한다.
add.o
를 생성한 방식과 동일한 방식으로 calc
의 나머지 종속 항목인 sub.o
와 main.o
를 생성한다.
- 이제 타겟
calc
를 만들기 위한 세 가지 종속 항목이 add.o
, sub.o
, main.o
가 모두 존재한다.
calc : add.o sub.o main.o
gcc -W -Wall -o calc add.o sub.o main.o
- 따라서
calc
타겟을 만들기 위해, 아래 명령어 gcc -W -Wall -o calc add.o sub.o main.o
를 수행한다.
calc
타겟이 생성됐으면, all
타겟의 종속 항목이 생성된 것이다.
all
타겟을 만들기 위한 명령어가 존재하지 않기에, make는 all
타겟이 생성된 것으로 간주하고 종료한다.
make
명령을 내릴 때 실행 인자로 특별한 타켓을 지정하지 않으면, Makefile에서 처음 만나는 타겟을 생성하려고 한다.
- make는 모든 타겟에 대하여 타겟의 생성시간과 종속항목의 최근 수정 시간을 비교한다.
- 만일 타겟이 모든 종속 항목들의 수정 시간보다 이후에 만들어졌으면, make는 새로 만들 필요가 없는 것으로 간주하여 명령을 수행하지 않는다.