Makefile 기본 문법
2021. 10. 6. 11:19ㆍ프로그래밍 언어/C∕C++
GNU Make 매뉴얼 : https://www.gnu.org/software/make/manual/html_node/
한국어 번역 : http://korea.gnu.org/manual/release/make/make-sjp/make-ko_toc.html
Make란
파일 관리 유틸리티.
파일간의 종속관계를 파악하여 Makefile에 적힌 대로 컴파일러에 명령하여 Shell 명령이 순차적으로 실행될 수 있게 한다.
Make의 장점
- 각 파일에 대한 반복적 명령의 자동화로 인한 시간 절약
- 프로그램의 종속 구조를 빠르게 파악할 수 있으며 관리가 용이
- 단순 반복 작업 및 재작성을 최소화
Make 옵션
make에서 거의 모든 것은 Makefile 내부에서 지정 가능하다. 그 중 일부는 make 실행시 사용 가능하다.
옵션 | 설명 |
-C dir |
Makefile을 계속 읽지 말고 우선은 dir로 이동하라는 것. 순환 make에 사용됨 |
-d , -debug |
Makefile을 수행하면서 각종 정보를 모두 출력 (출력량 多) |
-h , -help |
옵션에 관한 도움말을 출력 |
-f <filename> , -file <filename> |
<filename>에 해당하는 파일을 Makefile로 지정 |
-r , -no-builtin-rules> |
내장된 각종 규칙 (Suffix Rule 등)을 없는것으로 간주한다. 따라서 사용자가 규칙을 새롭게 정의해 주어야 함 |
-t , -touch |
파일의 생성 날짜를 현재 시간으로 갱신 |
-v , -version |
make의 버전을 출력 |
-p , -print-data-base |
make에서 내부적으로 세팅되어있는 값들을 출력 |
-k , -keep-going |
에러가 나더라도 멈추지 말고 계속 진행하게 하는 명령어 (make는 에러 발생시 도중에 실행을 중단한다.) |
Makefile의 구성
- Target (목표 파일) : 명령어 수행 후 나온 결과를 저장할 파일
- Dependency (의존성) : 목표 파일을 만들기 위해 필요한 구성요소
- Command (명령어) : 실행 되어야 할 명령어들
- Macro (매크로) : 코드를 단순화 시킴
Makefile의 기본 구조
CC = gcc # 매크로 정의
target1 : dependency1 dependency2
command1
command2
target2 : dependency3 dependency4
command1
command2
Makefile 작성규칙
# 타겟(목표 파일) : 의존성(목표 파일을 만드는데 필요한 구성요소들)
# 명령어(목적을 달성하기 위한 명령)
# 명령어(목적을 달성하기 위한 명령)
- 매크로 정의 : Makefile에 정의한 string으로 치환한다.
- 명령어의 시작은 반드시 탭(tab)으로 시작한다.
- Dependency가 없는 Target도 사용 하능하다.
변수 사용하기
명령어에서 변수 사용하기 (Using Variables in Recipes)
예제 :
LIST = one two three
all:
for i in $(LIST); do \
echo $$i; \
done
위의 예제의 경우, Shell에 아래와 같은 명령이 전달된다.
for i in one two three; do \
echo $i; \
done
또한 아래와 같은 결과가 나온다.
one
two
three
미리 정해져 있는 매크로 (Pre-defined Macro)
매크로 | 설명 |
ASFLAGS | as 명령어의 옵션 |
AS | as (=Assembler |
CFLAGS | cc의 옵션 |
CC | cc (=gcc, C compiler) |
CPPFLAGS | g++의 옵션 |
CXX | g++ (C++ compiler) |
LDFLAGS | ld 링커의 옵션 |
LD | 링크 (ld) |
LDLIBS | 링크 라이브러리 목록 |
LFLAGS | lex의 옵션 |
LEX | lex (LEX processor) |
YFLAGS | yacc의 옵션 |
YACC | yacc (YACC processor) |
OBJS | 중간 산출물 Object 파일 목록 |
TARGET | 빌드 대상(실행 파일) 이름 |
변수 | 설명 |
$@ | 현재 Target 이름 |
$* | 확장자가 없는 현재의 Target |
$% | 대상의 이름 (해당 규칙 대상이 archive인 경우) |
$< | 현재 Target이 의존하는 대상들 중 변경된 것들의 목록 |
$? | 현재 Target이 의존하는 대상들 중 변경된 것들의 목록 |
$^ | 현재 Target이 의존하는 대상들의 전체 목록 |
* 참고 : 책에서는 $<
와 $?
를 약간 구분하고 있지만 거의 같다고 봐도 무방하다.
Makefile 기본 패턴
CC=<컴파일러>
CFLAGS=<컴파일 옵션>
LDFLAGS=<링크 옵션>
LDLIBS=<링크 라이브러리 목록>
OBJS=<Object 파일 목록>
TARGET=<빌드 대상 이름>
all: $(TARGET)
clean:
rm -f *.o
rm -f $(TARGET)
$(TARGET): $(OBJS)
$(CC) -o $@ $(OBJS)
Makefile 예제
#---------------------------------------------------------------------
# M A K E F I L E
#---------------------------------------------------------------------
# CREATION DATE : YYYY.MM.DD
#---------------------------------------------------------------------
# Compile/load flags:
#---------------------------------------------------------------------
LIB_NAME = testLib.a
LOCAL_INC = -I./src -I./include
LOCAL_OPTIONS = -D_TEST
CPPFLAGS = $(LOCAL_INC) $(PRJ_INC) $(SOOPTIONS) $(LOCAL_OPTIONS)
LDFLAGS = $(LOCAL_LIB) $(PRJ_LIB) $(STD_LIB)
#---------------------------------------------------------------------
# Object File
#---------------------------------------------------------------------
LIB_OBJFILE = $(FLATFORM)/testLib.o
#---------------------------------------------------------------------
# Targets
#---------------------------------------------------------------------
init:
$(MKDIR) -p $(PLATFORM)
all: $(LIB_NAME)
$(LIB_NAME): $(LIB_OBJFILE)
$(AR) ruv $(LIBTARGET)/$@ $(LIB_OBJFILE)
clean:
$(RM) $(LIB_OBJFILE) *.exe core
$(RM) $(LIB_TARGET)/$(LIB_NAME)
#---------------------------------------------------------------------
# Pattern rule
#---------------------------------------------------------------------
$(LIB_OBJFILE): ./$(PLATFORM)/%.o: ./src/%.cpp
$(CCC) $(CPPFLAGS) -c $< -o $@
#---------------------------------------------------------------------
# End of Makefile
#---------------------------------------------------------------------
참고