[Linux] make - 1
- 프로그램 빌드 자동화 소프트웨어
- 여러 파일들 간의 의존성과 각 파일을 위한 명령어를 정의 한 Makefile을 해석하여 실행파일 또는 라이브러리를 빌드 함
- 따로 옵션을 주지 않을 경우 default로 Makefile 또는 makefile 파일을 찾고, 다른 이름의 파일을 넘겨 줄 경우에는 -f 옵션으로 파일 이름을 지정 함.
- 기본구조
Target: Dependencies
[TAB키] Commands
TAB키 부분에 SPACE키를 사용하면 안됨.
- Target - Command 실행 결과로 만들어 지게 되는 목적(object) 파일
- Dependencis - Target을 만들 때 의존성(연관관계)를 규정. 이 부분에 나열된 파일이 수정되면 command를 수행해서 target을 다시 만듦. 즉 target 파일의 최종 수정 시간과 dependencies에 있는 파일들의 최종 수정 시간을 비교해서 command 수행여부를 결정
- Command - Target을 만들기 위해 실행해야 하는 명령. command는 여러줄이 될 수도 있음.
- Comment - '#' 뒤에 오는 글자는 주석 처리 함.
Command 앞에 '@'을 붙여주면 그 명령은 화면에 출력 되지 않음.
# 커맨드 앞에 @를 붙이지 않은 경우
# Makefile
all:
echo hello
#----------------------------------------
$ make
echo hello
hello
# 커맨드 앞에 @를 붙인 경우
# Makefile
all:
@echo hello
#----------------------------------------
$ make
hello
예를 들어 다음과 같은 2개의 소스 파일과 1개의 헤더 파일이 있다고 할 때,
/* add.h */
int add(int x, int y);
// --------------------------------------------------------------------------------------------
/* add.c */
#include "add.h"
int add(int x, int y)
{
return x + y;
}
// --------------------------------------------------------------------------------------------
/* main.c */
#include <stdio.h>
#include "add.h"
int main(void)
{
int value = 0;
value = add(3, 5);
printf("%d\n", value);
return 0;
}
Makefile은 다음과 같이 작성 할 수 있다.
# Makefile
result: main.o add.o
gcc main.o add.o -o result
main.o: main.c
gcc -c main.c
add.o: add.c
gcc -c add.c
쉘에서 make 명령어를 입력하면, 오브젝트 파일과 실행 파일이 생성 된다.
그럼 이제 Makefile 을 조금씩 고쳐 나가 보자.
일단 변수를 사용하여 반복되는 커맨드를 대체 해 보자. 커맨드에서 반복되는 gcc를 다음과 같이 변수를 사용하여 대체 할 수 있다.
# Makefile
CC = gcc
result: main.o add.o
$(CC) main.o add.o -o result
main.o: main.c
$(CC) -c main.c
add.o: add.c
$(CC) -c add.c
gcc 부분은 개발환경에 따라 크로스컴파일러로도 변경 될 수 있으니, 나중에 CC 변수의 값만 변경 하면 된다.
그 다음단계는 변수를 좀 더 사용하여 컴파일러 옵션과 실행파일 및 의존파일을 대체 해 보자
# Makefile
CC = gcc
CFLAGS = -c
TARGET = result
OBJS = main.o add.o
$(TARGET): $(OBJS)
$(CC) $(OBJS) -o $(TARGET)
main.o: main.c
$(CC) $(CFLAGS) main.c
add.o: add.c
$(CC) $(CFLAGS) add.c
다음엔 내장 매크로를 사용하여 보자.
- $< : 의존관계 파일 중에 첫 번째 파일로 대치 됨
- $^ : 의존관계 파일 전체로 대치 됨
- $@ : target으로 대치 됨
- $* : 확장자가 없는 target 으로 대치 됨
- $? : 의존관계 파일 중에 target 보다 새로운 파일들 목록으로 대치 됨
의존관계에 있는 C 파일들을 커맨드라인에서 $< 를 사용하여 대치 해 보자.
# Makefile
CC = gcc
CFLAGS = -c
TARGET = result
OBJS = main.o add.o
$(TARGET): $(OBJS)
$(CC) $(OBJS) -o $(TARGET)
main.o: main.c
$(CC) $(CFLAGS) $<
add.o: add.c
$(CC) $(CFLAGS) $<
하지만 C 파일이 점점 늘어 날 수록 Makefile의 라인 수는 점점 늘어날 것이므로 문제가 된다.
중복이 발생 하는 부분은 C 소스파일을 컴파일하여 오브젝트 파일을 만든다는 부분이다.
다음과 같은 방법으로 획기적으로 중복이 발생 하는 부분을 줄일 수 있게 된다.
# Makefile
CC = gcc
CFLAGS = -c
TARGET = result
OBJS = main.o add.o
$(TARGET): $(OBJS)
$(CC) $(OBJS) -o $(TARGET)
%.o: %.c
$(CC) $(CFLAGS) $<
최종적으로 오브젝트 파일과 실행파일을 정리할 수 있는 clean 더미 타겟을 추가하고, 내장 매크로를 사용하면 다음과 같이 Makefile을 작성 할 수 있다.
# Makefile
CC = gcc
CFLAGS = -c
TARGET = result
OBJS = main.o add.o
$(TARGET): $(OBJS)
$(CC) $^ -o $@
%.o: %.c
$(CC) $(CFLAGS) $<
clean:
rm -rf $(OBJS) $(TARGET)