Makefile (3)
8. Makefile - 패턴 규칙(pattern rule)
더보기


1. 문제

2. 패턴 규칙 기본 구조
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
- 보통 .c 파일을 .o 파일로 컴파일하는 규칙처럼, 동일한 형식의 명령을 여러 파일에 반복 적용할 때 사용
- %.o: %.c
- % 는 와일드카드(wildcard) 같은 역할
- %.o : 대상 파일 패턴, .o 확장자를 가진 파일
- %.c : 의존성 파일 패턴, 동일한 이름의 .c 파일
- main.o 는 main.c 에 대응되고, foo.o 는 foo.c 에 대응됩니다.
- $(CC)
- 컴파일러 명령어(gcc 등)를 의미
- $(CFLAGS)
- 컴파일 옵션 (예: -g -Wall)
- -c
- 옵션은 컴파일만 하고 목적파일까지만 만들고, 링크하지 않겠다는 의미
- $<
- 첫 번째 의존성(dependency) 파일, 여기서는 %.c에 해당하는 소스 파일
- main.o 를 빌드할 때 $< 는 main.c
- $@
- 현재 타겟 이름을 의미, 여기서는 %.o에 해당하는 오브젝트 파일
- main.o 를 빌드할 때 $@ 는 main.o 가 됩니다.
3. 예시5(패턴 적용)

# 컴파일러와 실행파일 이름 설정
CC = gcc
TARGET = myprogram
# 소스 파일 목록과 오브젝트 파일 자동 생성
SRCS = main.c foo.c bar.c #baz.c
OBJS = main.o foo.o bar.o #baz.o
# all 타겟: 최종 실행파일 빌드
all: $(TARGET)
# 실행파일 생성
$(TARGET): $(OBJS)
$(CC) $(OBJS) -o $@
# 오브젝트 파일 생성 규칙
%.o: %.c
$(CC) -c $< -o $@
# clean 타겟: 빌드 산출물 삭제
clean:
rm -f $(TARGET) *.o
9. Makefile - 변수 치환 (Variable Substitution)
더보기


1. 문제

2. 변수 치환 기본 구조
$(변수명:패턴=대체문자열)
- 변수 변수명의 값 중에서, 패턴에 해당하는 부분을 찾아 대체문자열로 모두 변경
SRCS = main.c foo.c bar.c
OBJS = $(SRCS:.c=.o) # → main.o foo.o bar.o
- SRCS 변수에 .c 확장자를 가진 소스 파일 리스트가 들어있을 때,
$(SRCS:.c=.o) 는 SRCS에 있는 각 파일 이름에서 .c를 .o로 바꾼 리스트를 생성 - 결과: OBJS = main.o foo.o bar.o
- 소스 파일이 많거나 추가될 때마다 일일이 오브젝트 파일 이름을 수정할 필요 없이
소스 리스트만 변경하면 자동으로 오브젝트 파일 리스트가 생성되어 편리합니다.
3. 예시6(치환 적용)

# 컴파일러와 실행파일 이름 설정
CC = gcc
TARGET = myprogram
# 소스 파일 목록과 오브젝트 파일 자동 생성
SRCS = main.c foo.c bar.c # baz.c
OBJS = $(SRCS:.c=.o)
# all 타겟: 최종 실행파일 빌드
all: $(TARGET)
# 실행파일 생성
$(TARGET): $(OBJS)
$(CC) $(OBJS) -o $@
# 오브젝트 파일 생성 규칙
%.o: %.c
$(CC) -c $< -o $@
# clean 타겟: 빌드 산출물 삭제
clean:
rm -f $(TARGET) *.o
99. Makefile 주의사항
더보기
1. 탭 문자 대신 스페이스 사용 시 오류 발생
- 명령어 앞에 반드시 탭 문자여야 하며, 스페이스로 대체하면 missing separator 오류 발생
- 에디터 설정에서 탭을 스페이스로 자동 변환하지 않도록 주의
2. 변수 사용 시 공백 주의
- 변수 할당 시 = 앞뒤에 공백이 없도록 작성하는 것이 일반적
CC = gcc # 올바름 CC= gcc # 권장하지 않음 (왼쪽 공백은 무시되나 혼란 방지 위해 권장하지 않음)
- makefile 변수 참조는 $(변수명) 또는 ${변수명} 형태로 사용
3. 주석은 # 으로 시작
- Makefile 내 주석은 # 뒤부터 줄 끝까지 무시됨
4. 명령어 줄은 여러 줄로 나눌 수 있음
- \ 문자로 명령어를 여러 줄에 나눠 쓸 수 있음
-
target: gcc -c foo.c && \ gcc -c bar.c && \ gcc foo.o bar.o -o myprogram
5. .PHONY 타겟 선언
- 실제 파일과 이름이 겹치는 가상 타겟(예: clean, all)은 .PHONY로 선언하는 게 좋음
- 그래야 파일이 있더라도 명령어가 항상 실행됨
6. 패턴 규칙과 자동 변수 활용
- %.o: %.c 같은 패턴 규칙을 사용해 중복 코드를 줄이고 유지보수 편리
- $@, $<, $^ 같은 자동 변수 적극 활용
7. 환경변수 영향
- Makefile 내 변수는 쉘 환경 변수와 다를 수 있음
- 쉘 명령어 실행 시 쉘 환경 변수 영향을 받을 수 있으니 주의
8. 병렬 빌드 지원
- make -j N 옵션으로 병렬 빌드 가능
- 타겟 간 의존성 명확히 작성해야 안전하게 병렬 빌드 가능