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 옵션으로 병렬 빌드 가능
  • 타겟 간 의존성 명확히 작성해야 안전하게 병렬 빌드 가능