Makefile - 4. 고급 Makefile 작성 (4-1. 다중 디렉토리 관리 (Managing Multiple Directories))
2025. 3. 11. 19:08ㆍ개발/개발도구와 환경
📌 4-1. 다중 디렉토리 관리 (Managing Multiple Directories)
대규모 프로젝트에서는 소스 코드가 여러 개의 서브 디렉토리(Subdirectories)에 분산될 수 있습니다.
이때, 각각의 서브 디렉토리에서 Makefile을 실행하면 빌드를 더욱 효율적으로 관리할 수 있습니다.
Makefile에서 다중 디렉토리를 관리하는 대표적인 방법으로 다음과 같은 기법이 사용됩니다.
- SUBDIRS 패턴을 사용하여 서브 디렉토리별로 make 실행
- make -C subdir을 활용하여 서브 디렉토리에서 개별적으로 빌드 수행
1. 다중 디렉토리를 관리하는 이유
📌 1-1. 왜 다중 디렉토리 관리가 필요한가?
✅ 대규모 프로젝트 관리 용이
- 하나의 Makefile에서 모든 소스 파일을 관리하는 것은 비효율적
- 디렉토리별로 Makefile을 분리하면 모듈 단위로 관리 가능
✅ 빌드 속도 향상
- 특정 디렉토리에서 변경된 파일만 다시 빌드 가능
- 서브 디렉토리 단위로 병렬 빌드(make -j) 수행 가능
✅ 재사용성 증가
- 라이브러리(lib/), 실행 파일(bin/), 소스 코드(src/) 등으로 분리하여 유지보수 편리
2. SUBDIRS 패턴을 활용한 서브 디렉토리 Makefile 실행
📌 2-1. SUBDIRS를 활용한 다중 디렉토리 관리
Makefile에서 서브 디렉토리를 순차적으로 빌드하기 위해 SUBDIRS 변수를 사용하여 관리할 수 있습니다.
📌 2-2. SUBDIRS 활용 예제
🔹 프로젝트 구조
project/
├── src/
│ ├── main.c
│ ├── utils.c
│ ├── Makefile
├── lib/
│ ├── math.c
│ ├── Makefile
├── bin/
│ ├── Makefile
├── Makefile (최상위 Makefile)
🔹 project/src/Makefile
CC = gcc
CFLAGS = -Wall -g
SRC = main.c utils.c
OBJS = $(SRC:.c=.o)
all: $(OBJS)
$(CC) $(CFLAGS) -c $^
clean:
rm -f $(OBJS)
🔹 project/lib/Makefile
CC = gcc
CFLAGS = -Wall -g
SRC = math.c
OBJS = $(SRC:.c=.o)
all: $(OBJS)
$(CC) $(CFLAGS) -c $^
clean:
rm -f $(OBJS)
🔹 project/bin/Makefile
CC = gcc
CFLAGS = -Wall -g
LDFLAGS = -L../lib
LDLIBS = -lmath
all: myprogram
myprogram: ../src/main.o ../src/utils.o ../lib/math.o
$(CC) $(CFLAGS) $(LDFLAGS) -o myprogram $^ $(LDLIBS)
clean:
rm -f myprogram
🔹 project/Makefile (최상위 Makefile)
SUBDIRS = lib src bin
all:
for dir in $(SUBDIRS); do $(MAKE) -C $$dir; done
clean:
for dir in $(SUBDIRS); do $(MAKE) -C $$dir clean; done
✅ 설명
- SUBDIRS 변수를 활용하여 lib/, src/, bin/ 디렉토리를 순차적으로 빌드
- $(MAKE) -C $$dir를 사용하여 각 디렉토리에서 make 실행
- clean 목표를 실행하면 각 디렉토리의 clean이 실행됨
✅ 실행 과정
make
➡ lib/Makefile 실행
➡ src/Makefile 실행
➡ bin/Makefile 실행
make clean
➡ lib/Makefile의 clean 실행
➡ src/Makefile의 clean 실행
➡ bin/Makefile의 clean 실행
3. make -C subdir를 활용한 서브 디렉토리 빌드
📌 3-1. make -C의 개념
- make -C subdir 명령을 사용하면 서브 디렉토리로 이동한 후 Makefile을 실행할 수 있습니다.
- cd subdir && make를 실행하는 것과 동일한 효과
📌 3-2. make -C 활용 예제
🔹 project/Makefile (최상위 Makefile)
all:
$(MAKE) -C lib
$(MAKE) -C src
$(MAKE) -C bin
clean:
$(MAKE) -C lib clean
$(MAKE) -C src clean
$(MAKE) -C bin clean
✅ 실행 과정
make
➡ make -C lib 실행
➡ make -C src 실행
➡ make -C bin 실행
make clean
➡ make -C lib clean 실행
➡ make -C src clean 실행
➡ make -C bin clean 실행
📌 3-3. make -C를 활용한 빌드 옵션 전달
- make -C를 사용할 때, 변수를 전달할 수도 있음
make -C src DEBUG=1
➡ src/Makefile에서 DEBUG=1을 적용하여 빌드 수행
make -C lib CC=clang
➡ lib/Makefile에서 CC=clang을 적용하여 clang으로 빌드
4. SUBDIRS vs make -C 차이점
방법 | 설명 | 장점 | 단점 |
SUBDIRS 패턴 | for dir in $(SUBDIRS); do $(MAKE) -C $$dir; done | 여러 디렉토리를 반복적으로 빌드 가능 | 쉘 스크립트 구문이므로 일부 환경에서 오류 가능 |
make -C | $(MAKE) -C src | 각 디렉토리를 독립적으로 실행 가능, 가독성 높음 | 디렉토리 수가 많으면 반복 코드 증가 |
✅ 추천
- 소규모 프로젝트: make -C가 가독성이 좋음
- 대규모 프로젝트: SUBDIRS 패턴이 확장성이 뛰어남
📌 4-1. 다중 디렉토리 관리 요약 정리
개념 | 설명 |
SUBDIRS 패턴 | for 루프를 사용하여 서브 디렉토리 빌드를 반복 실행 |
make -C subdir | 특정 디렉토리에서 make를 실행 |
다중 Makefile 관리 | 서브 디렉토리별 Makefile을 사용하여 프로젝트를 모듈화 |
변수 전달 (make -C) | make -C src DEBUG=1 처럼 특정 빌드 옵션 전달 가능 |