Makefile - 4. 고급 Makefile 작성 (4-3. 빌드 캐싱 및 증분 빌드 (Build Caching & Incremental Build))

2025. 3. 11. 19:11개발/개발도구와 환경

📌 4-3. 빌드 캐싱 및 증분 빌드 (Build Caching & Incremental Build)

빌드 속도를 최적화하는 핵심 기법 중 하나는 빌드 캐싱(Build Caching)과 증분 빌드(Incremental Build)입니다.
이를 통해 변경된 파일만 다시 컴파일하여 불필요한 빌드를 방지하고, 전체 빌드 시간을 단축할 수 있습니다.

대표적인 방법으로 touch를 활용한 최신 빌드 관리ccache를 활용한 컴파일 캐싱이 있습니다.


1. 빌드 캐싱(Build Caching) 및 증분 빌드(Incremental Build)란?

📌 1-1. 빌드 캐싱과 증분 빌드 개념

  • 증분 빌드(Incremental Build)
    • 변경된 파일만 다시 컴파일하고, 변경되지 않은 파일은 재사용.
    • Makefile의 의존성(Dependency) 관리를 통해 자동 수행됨.
  • 빌드 캐싱(Build Caching)
    • 이전에 컴파일한 결과를 저장하고, 같은 입력이 들어오면 기존 결과를 재사용.
    • 대표적인 도구: ccache (컴파일 결과 캐싱)

📌 1-2. 빌드 캐싱 및 증분 빌드의 필요성

빌드 속도 최적화

  • 전체 프로젝트를 다시 빌드하는 것이 아니라, 변경된 파일만 다시 컴파일.
  • ccache를 사용하면 이전 컴파일 결과를 재활용하여 속도를 더욱 향상.

개발 생산성 향상

  • 코드 변경 시 즉각적인 빌드 및 테스트 가능.
  • 특히 대규모 프로젝트에서는 필수적인 최적화 기법.

CI/CD(지속적 통합 및 배포) 환경에서 필수

  • GitLab CI/CD, Jenkins 같은 자동화 환경에서도 빌드 시간을 최소화.

2. touch를 활용한 최신 빌드 관리

📌 2-1. touch 명령어란?

  • touch 명령어는 파일의 수정 시간을 변경하는 유닉스 명령어.
  • Makefile에서 특정 파일을 강제로 최신 상태로 유지할 때 사용 가능.
touch filename

➡ filename의 수정 시간을 현재 시간으로 업데이트.


📌 2-2. touch를 활용한 증분 빌드

Makefile에서 touch를 활용하면 강제로 파일을 최신 상태로 만들어 불필요한 재컴파일을 방지할 수 있습니다.

🔹 예제 1: touch를 활용한 최신 빌드 관리

CC = gcc
CFLAGS = -Wall -g
SRC = main.c utils.c
OBJS = $(SRC:.c=.o)
TARGET = myprogram

all: $(TARGET)

$(TARGET): $(OBJS)
	$(CC) $(CFLAGS) -o $@ $^
	touch $@

%.o: %.c
	$(CC) $(CFLAGS) -c $< -o $@

clean:
	rm -f $(OBJS) $(TARGET)

설명

  • $(TARGET): $(OBJS) 빌드 후 touch $@를 실행하여 myprogram의 시간을 최신으로 변경.
  • 다음번 make 실행 시 변경되지 않은 경우 재컴파일을 방지.

실행 과정

make

➡ gcc -c 실행 후 gcc -o myprogram 실행됨.

make

파일이 최신 상태이므로 다시 빌드되지 않음.


📌 2-3. touch를 활용한 강제 빌드 트리거

파일을 강제로 재컴파일하려면 touch를 활용하여 특정 파일을 오래된 상태로 만들 수 있음.

touch main.c
make

➡ main.c의 시간이 업데이트되었으므로 main.o가 다시 컴파일됨.

touch $(OBJS)
make

➡ 모든 .o 파일을 재컴파일 없이 최신 상태로 유지.


3. ccache를 활용한 빌드 캐싱

📌 3-1. ccache란?

  • ccache는 C/C++ 컴파일 결과를 캐싱하여 동일한 빌드를 재사용하는 도구.
  • 동일한 입력(소스 코드, 컴파일 옵션 등)이 들어오면 기존 결과를 사용하여 재컴파일을 방지.

ccache의 장점

  • 중복된 컴파일 방지 → 빌드 속도 극대화.
  • 클린 빌드(make clean && make) 후에도 속도 유지.
  • CI/CD 환경에서 빠른 빌드 수행 가능.

📌 3-2. ccache 설치 및 설정

1️⃣ ccache 설치

Ubuntu/Debian:

sudo apt install ccache

Mac (Homebrew):

brew install ccache

Fedora:

sudo dnf install ccache

2️⃣ ccache를 Makefile에서 활용

기본적으로 ccache는 컴파일러 앞에 위치하여 실행됩니다.

CC = ccache gcc
CFLAGS = -Wall -g
SRC = main.c utils.c
OBJS = $(SRC:.c=.o)
TARGET = myprogram

all: $(TARGET)

$(TARGET): $(OBJS)
	$(CC) $(CFLAGS) -o $@ $^

%.o: %.c
	$(CC) $(CFLAGS) -c $< -o $@

clean:
	rm -f $(OBJS) $(TARGET)

설명

  • CC = ccache gcc를 사용하여 gcc 대신 ccache gcc가 실행되도록 설정.
  • 이미 컴파일된 파일이면 컴파일을 생략하고 캐시된 결과 사용.

📌 3-3. ccache 사용 예제

🔹 ccache 적용 전후 비교

time make

➡ 전체 빌드 수행 (오랜 시간 소요).

time make

변경된 파일이 없으면 즉시 완료됨 (캐시 적용됨).


📌 3-4. ccache 상태 확인

ccache의 캐시 상태를 확인하려면 다음 명령어를 실행:

ccache -s

➡ 캐시된 파일 개수, 히트율(Cache Hit Rate), 캐시 크기 등을 확인 가능.


📌 4-3. 빌드 캐싱 및 증분 빌드 요약 정리

기법  설명
touch 활용 특정 파일을 최신 상태로 유지하여 불필요한 재컴파일 방지
파일 강제 재컴파일 touch main.c를 실행하면 해당 파일만 다시 컴파일
ccache 사용 이전 컴파일 결과를 저장하여 동일한 입력 시 캐시된 결과 사용
ccache 장점 클린 빌드 후에도 속도 유지, CI/CD 환경에서 필수