Makefile - 5. Makefile 최적화 및 실전 프로젝트 적용 (5-3. 실제 프로젝트에서 Makefile 적용)
2025. 3. 11. 19:16ㆍ개발/개발도구와 환경
📌 5-3. 실제 프로젝트에서 Makefile 적용
Makefile을 활용하면 대규모 프로젝트에서도 효율적인 빌드 시스템을 구축할 수 있습니다.
이번 섹션에서는 실제 프로젝트 구조를 기반으로 Makefile을 작성하는 방법을 살펴보겠습니다.
1. 프로젝트 구조 예시
다음과 같은 프로젝트 구조를 예제로 사용합니다.
project/
├── src/ # 소스 코드 디렉토리
│ ├── main.c
│ ├── utils.c
│ └── utils.h
├── include/ # 헤더 파일 저장 디렉토리
│ └── config.h
├── build/ # 빌드된 오브젝트 파일과 실행 파일이 저장될 디렉토리
├── Makefile # 프로젝트 빌드를 위한 Makefile
✅ 각 디렉토리의 역할
- src/ : C 소스 코드 (.c, .h 파일 포함)
- include/ : 전역적으로 사용되는 헤더 파일 (config.h)
- build/ : 빌드된 오브젝트 파일(.o) 및 실행 파일을 저장
- Makefile : 빌드 자동화 규칙을 정의하는 파일
2. Makefile 작성: 기본 구조
이제 프로젝트 구조에 맞춰 Makefile을 작성해보겠습니다.
이 Makefile은 다음 기능을 포함합니다.
✅ 기능
- src/ 디렉토리의 .c 파일을 자동으로 build/ 디렉토리에 컴파일.
- include/ 디렉토리에 있는 헤더 파일을 포함하도록 설정.
- clean 명령을 추가하여 불필요한 파일 삭제 가능.
📌 2-1. 기본적인 Makefile
# 컴파일러 및 플래그 설정
CC = gcc
CFLAGS = -Wall -g -Iinclude
# 디렉토리 설정
SRCDIR = src
BUILDDIR = build
# 소스 및 오브젝트 파일 설정
SRC = $(wildcard $(SRCDIR)/*.c)
OBJS = $(patsubst $(SRCDIR)/%.c, $(BUILDDIR)/%.o, $(SRC))
# 실행 파일 이름
TARGET = $(BUILDDIR)/myprogram
# 기본 빌드 실행
all: $(TARGET)
# 실행 파일 빌드
$(TARGET): $(OBJS)
$(CC) $(CFLAGS) -o $@ $^
# 개별 .c -> .o 파일 변환 규칙
$(BUILDDIR)/%.o: $(SRCDIR)/%.c | $(BUILDDIR)
$(CC) $(CFLAGS) -c $< -o $@
# build 디렉토리가 없으면 생성
$(BUILDDIR):
mkdir -p $(BUILDDIR)
# 클린 빌드 (불필요한 파일 제거)
clean:
rm -rf $(BUILDDIR)
📌 2-2. Makefile 설명
구성 요소 |
설명 |
CC = gcc | 컴파일러로 gcc 사용 |
CFLAGS = -Wall -g -Iinclude | 경고 표시 -Wall, 디버깅 -g, include/ 헤더 포함 |
SRCDIR = src | 소스 파일이 위치한 디렉토리 |
BUILDDIR = build | 빌드된 .o 및 실행 파일을 저장할 디렉토리 |
SRC = $(wildcard $(SRCDIR)/*.c) | src/ 디렉토리의 모든 .c 파일 목록을 자동으로 가져옴 |
OBJS = $(patsubst $(SRCDIR)/%.c, $(BUILDDIR)/%.o, $(SRC)) | .c 파일을 .o 파일로 변환하여 build/ 디렉토리에 저장 |
$(TARGET): $(OBJS) | 오브젝트 파일들을 링크하여 실행 파일 생성 |
$(BUILDDIR)/%.o: $(SRCDIR)/%.c | 개별 .c 파일을 .o 파일로 변환 |
$(BUILDDIR): | build/ 디렉토리가 없으면 생성 |
clean: | build/ 디렉토리를 삭제하여 클린 빌드 수행 |
3. Makefile 실행 과정
✅ 빌드 실행
make
➡ 실행 결과:
mkdir -p build
gcc -Wall -g -Iinclude -c src/main.c -o build/main.o
gcc -Wall -g -Iinclude -c src/utils.c -o build/utils.o
gcc -Wall -g -o build/myprogram build/main.o build/utils.o
✅ 실행 파일 생성 완료 (build/myprogram)
✅ 클린 빌드 실행
make clean
➡ 실행 결과:
rm -rf build
✅ build/ 디렉토리 삭제 및 초기화 완료
4. Makefile 확장: 디버그 및 최적화 모드 추가
디버깅이나 최적화가 필요할 경우, 다음과 같이 DEBUG 및 OPTIMIZE 모드를 추가할 수 있습니다.
# 기본 플래그 설정
CC = gcc
CFLAGS = -Wall -Iinclude
# 디버그 모드
ifdef DEBUG
CFLAGS += -g -DDEBUG
endif
# 최적화 모드
ifdef OPTIMIZE
CFLAGS += -O2
endif
# 기본 설정
SRCDIR = src
BUILDDIR = build
SRC = $(wildcard $(SRCDIR)/*.c)
OBJS = $(patsubst $(SRCDIR)/%.c, $(BUILDDIR)/%.o, $(SRC))
TARGET = $(BUILDDIR)/myprogram
all: $(TARGET)
$(TARGET): $(OBJS)
$(CC) $(CFLAGS) -o $@ $^
$(BUILDDIR)/%.o: $(SRCDIR)/%.c | $(BUILDDIR)
$(CC) $(CFLAGS) -c $< -o $@
$(BUILDDIR):
mkdir -p $(BUILDDIR)
clean:
rm -rf $(BUILDDIR)
✅ 디버그 빌드 실행
make DEBUG=1
➡ -g -DDEBUG 플래그 추가됨.
✅ 최적화 빌드 실행
make OPTIMIZE=1
➡ -O2 플래그 추가됨.
📌 5-3. 실제 프로젝트에서 Makefile 적용 요약 정리
Makefile 기능 | 설명 |
SRC = $(wildcard $(SRCDIR)/*.c) | src/ 디렉토리의 .c 파일을 자동으로 가져옴 |
OBJS = $(patsubst $(SRCDIR)/%.c, $(BUILDDIR)/%.o, $(SRC)) | .c 파일을 .o 파일로 변환 |
$(BUILDDIR)/%.o: $(SRCDIR)/%.c | .c 파일을 build/ 디렉토리의 .o 파일로 변환 |
DEBUG=1 | -g -DDEBUG 플래그 추가 |
OPTIMIZE=1 | -O2 플래그 추가 |
make clean | 빌드된 파일을 삭제하여 클린 빌드 수행 |