목차
개요
출처: 트위터
기존에 사용하던 Makefile 은 소스 파일과 같은 경로에 생성하도록 했다.
예를 들면 아래와 같다.
.
├── Makefile
├── program.c
├── program.o
└── program.h
Plain Text
복사
소스 파일이 적을 때는 크게 불편한 점이 없었는데, 소스 파일 개수가 많아지면서 문제가 생겼다.
원하는 파일로 이동하기 위해서 마우스 스크롤을 많이 내려야했다.
Minishell 프로젝트 당시
위의 이미지처럼 한참 스크롤을 내려야 원하는 파일에 도달할 수 있었다.
개발할 때 생산성이 굉장히 중요하다고 생각하는데, 파일을 찾기 위한 시간도 단축하고 싶었다.
그래서 오브젝트 파일을 별도의 폴더에 분리하여 생산성을 높이고자 했다.
목표
원하는 폴더 구조는 다음과 같았다.
.
├── Makefile
├── program.c
├── program
├── program.h
└── obj
└── program.o
Plain Text
복사
이번 글에서는 위와 같이 가장 간단한 예시로 진행하고자 한다.
과정
1. 오브젝트 폴더 변수 생성
우선 오브젝트 파일을 저장할 폴더를 생성해야 한다.
그 전에 오브젝트 폴더의 이름을 정해주었다.
오브젝트 폴더의 이름은 obj 로 설정했고, 이를 변수로 선언해주었다.
OBJ_DIR := obj
Makefile
복사
오브젝트 파일마다 오브젝트 폴더의 경로를 추가해준다.
2. 오브젝트 파일 경로 설정
아래의 예시에서는 OBJS_FILES 변수에 저장했다.
SRCS := program.c
OBJS := $(SRCS:%.c=%.o)
OBJ_DIR := obj
OBJS_FILES := $(addprefix $(OBJ_DIR/, $(OBJS)
Makefile
복사
OBJS_FILES 변수에는 다음과 같이 저장된다.
obj/program.o
Plain Text
복사
3. 의존성 설정
program 이라는 파일을 생성하기 위해 아래와 같이 작성한다.
NAME := program
$(NAME) : $(OBJ_FILES)
$(CC) $(CFLAGS) -o $@ $^
$(OBJ_DIR):
mkdir -p $(OBJ_DIR)
$(OBJ_DIR)/%.o : %.c | $(OBJ_DIR)
$(CC) $(CFLAG) -c $< -o $@
Makefile
복사
설명을 추가하면, 오브젝트 폴더를 만들기 위해서 아래와 같이 작성했다.
$(OBJ_DIR):
mkdir -p $(OBJ_DIR)
Makefile
복사
오브젝트 폴더에 .c 파일을 모아서 컴파일 하도록 아래와 같이 작성했다.
$(OBJ_DIR)/%.o : %.c | $(OBJ_DIR)
$(CC) $(CFLAG) -c $< -o $@
Makefile
복사
여기서 눈 여겨봐야 하는 점은 %.c | $(OBJ_DIR) 이다.
중간에 들어간 | 은 order-only prerequisites 라 불린다.
이것이 하는 기능은 | 이전에 오는 레시피가 업데이트 되었을 경우에만 명령을 수행한다는 것이다.
즉, .c 파일이 수정되었을 때만 컴파일을 수행한다는 것이다.
그럼 만약 | 이 없다면 어떻게 될까?
아래와 같이 작성하고 make 를 입력해보면 정상적으로 작동한다.
$(OBJ_DIR)/%.o : %.c $(OBJ_DIR)
$(CC) $(CFLAG) -c $< -o $@
Makefile
복사
하지만, 다시 한번 make 를 입력하면 다시 컴파일이 진행되는 것을 알 수 있다.
다시 말해, 리링크가 발생하는 것이다.
이를 방지하기 위해 | 를 사용하는 것으로 이해하면 된다.
그래서 | 를 입력하고 make 를 실행하면 아래와 같이 작동한다.