gcc -c 를 이용한 object 파일 생성
gcc -o 를 이용해 바이너리 파일 생성
compile.sh >>
#! /bin/bash
gcc -c hello.c
gcc -c main.c
gcc -o hello hello.o main.o
위 스크립트의 문제점이 무엇일까?
프로젝트의 크기가 커진다면 컴파일할 파일도 많아질 것이다. 하지만 위 스크립트는 모든 파일을 다 컴파일해야 된다
--> 파일에 소스가 바뀌었는지를 계속 체크해야하고 바뀐 목적 파일만 새로 컴파일하는 기능이 추가되어야 한다!!!
Makefile >>
.PHONY: all clean
all : hello
hello.o : hello.c <-- 초단위로 기록을 하기때문에 이전 코드가 바뀐 것을 확인
gcc -c hello.c
main.o : main.c
gcc -c main.c
hello : hello.o main.o
gcc -o hello hello.o main.o
clean :
rm *.o
rm hello
Makefile >>
CC = gcc
CFLAGS += -std=c11
CFLAGS += -Wall -Werror
LDFLAGS += -lc
TARGET = hello
.PHONY: all clean
all : $(TARGET)
hello.o : hello.c <-- 초단위로 기록을 하기때문에 이전 코드가 바뀐 것을 확인
$(CC) -c $< $(CFLAGS)
main.o : main.c
$(CC) -c $< $(CFLAGS) $<: 목적 파일의 제일 첫번째 값
$(TARGET) : hello.o main.o
$(CC) -o $@ $^ $(LDFLAGS) <-- $@: target, $^: 목적 파일 모두
clean :
rm *.o
rm $(TARGET)
Makefile >>
CC = gcc
CFLAGS += -std=c11
CFLAGS += -Wall -Werror
LDFLAGS += -lc
TARGET = hello
OBJECTS = hello.o main.o <-- 생성하고자 하는 파일 더 추가해도 아래 소스를 바꿀 필요가 없다
.PHONY: all clean
all : $(TARGET)
.c.o : <-- .c로 .o 파일을 만들 수 있다
$(CC) -c $< $(CFLAGS)
$(TARGET) : $(OBJECTS )
$(CC) -o $@ $^ $(LDFLAGS)
clean :
rm *.o
rm $(TARGET)
재귀적으로 make하는 법
core, tester라는 폴더 안에 Makefile 각각 생성
Makefile >>
CC = gcc
CFLAGS += -std=c11
CFLAGS += -Wall -Werror
LDFLAGS += -lc
TARGET = hello test
SUBTARGET = ./core/hello ./tester/test
SUBDIRS = core tester
.PHONY: all clean dotest
all : $(TARGET)
$(TARGET) : $(SUBTARGET)
cp $(SUBTARGET) ./
$(SUBTARGET) :
for i in $(SUBDIRS); do \
cd $$i; \
make; \
cd ..; \
done <-- shell에서의 $i를 나타내기 위해 $를 한번 더 붙여줘야 함
clean :
for i in $(SUBDIRS); do cd $$i; make clean; cd ..; done
rm $(TARGET)
dotest :
./test
Makefile 매크로
1 # 주석
2 정의되지 않는 매크로는 null 문자열로 치환
3 중복된 정의는 최후에 정의된 값을 사용
4 여러 대입 기법 사용 가능
재귀적 확장 매크로 - 나중에 정의된 모든 변수 값을 치환하여 적용
ex) NAME1 = string
단순 확장 매크로 - 해당 시점의 변수 값만을 치환
ex) NAME1 := string
'?='는 정의되지 않은 경우 대입
컴파일할 타겟이 늘어난다면??
방법1
SRCS = $(wildcard .c) <-- 매크로 $(wildcard .c)는 현재 디렉토리에서 *.c 와 파일명이 일치하는 파일 찾음
OBJECTS = $(SRCS: .c=.o) <-- 대입참조 기법
방법2
OBJECTS = $(patsubst %.c, %.o, $(wildcard *.c)) <-- patsubst 문자열 처리, %는 확장자를 제외한 파일명
.SILENT
.IGNORE
조건부 수행
ifeq ~ else ~ endif
ex)
all :
ifeq ($ (CC), gcc)
@echo "C 컴파일러 GNU gcc 입니다"
else
@echo "C 컴파일러는 $(CC) 입니다"
endif
함수의 사용
1 셀 명령 함수
$(shell 셀 명령)
2 문자열 처리 함수
2-1 문자열 치환 함수
$(subst 찾을 문자, 변경할 문자, 목표 문자)
ex)
STR = $(subst like, LIKE, I like you)
echo :
@echo $(STR) --> I LIKE you
$(patsubst 패턴, 변경 문자열, 목표 문자열)
ex)
STR = $(patsubst %.c, %.o, memo.c main.c ABCD)
echo :
@echo $(STR) --> memo.o main.o ABCD
2-2 문자를 정렬하는 함수
$(sort 문자열)
2-3 공백 문자 제거
$(strip 문자열)
2-4 문자 필터링 함수
$(filter 패턴, 문자열)
ex)
FILES = memo.c head.h main.c asm.S diary.h
SRCS = $(filter %.c %.S, $(FILES))
HEADS = $(filter %.h, $(FILES))
echo :
@echo "source files : $(SRCS)" --> source files : memo.c main.c asm.S
@echo "head files : $(HEADS)"
2-5 특정 문자열을 찾는 함수
$(findstring 찾을 문자열, 대상 문자열)
$(words 문자열)
ex) $(words aa bb cc) --> 3
$(word n, 문자열)
ex) $(word 2, I like you) --> like
$(wordlist 시작번호, 끝 번호, 문자열)
ex) $(wordlist 2, 4, aa bb cc dd ee) --> bb cc dd
$(firstword 문자열)
ex) $(firstword I like you) --> I
$(join 문자열, 문자열)
ex) $(join src asm, .c .S) --> src.c asm.S
3 파일 이름 관련 함수
$(dir 문자열)
디렉토리들만 추출
ex)
PATHS = /bin/ls /sbin/ifconfig memo/memo.c Makefile
echo :
@echo $(dir $(PATHS)) --> /bin/ /sbin/ memo/ ./
$(suffix 문자열)
확장자들만 추출
ex)
FILES = src/memo.c asm/asm.S for.f ls /etc/resolv.conf
echo :
@echo $(suffix $(FILES)) --> .c .S .f .conf
$(basename 문자열)
점과 확장자를 제외한 순수한 파일명만 추출
$(addsuffix 접미사, 문자열)
문자열 각 뒤에 접미사를 붙여준다
$(addprefix 접두어, 문자열)
문자열 각 뒤에 접두어를 붙여준다
3 기타 유용한 함수
$(foreach 변수명, 대입 문자열, 확장 문자열)
ex)
SRCS = $(foreach str, a b c, $(str) .c)
echo :
@echo $(SRCS) --> a.c b.c c.c