본문 바로가기

프로그래밍/Linux

[study] Makefile

 

Makefile이 필요한 이유

1. 반복되는 컴파일 작업이 오래 걸리기 때문이다.

2. 수정된 파일만 컴파일 할 수 있다.

3. 대규모 프로젝트, 공동 프로젝트에서 반드시 필요하다.

 

Makefile 이해

*.c (소스파일) -> 인간이 이해하는 언어 (vi, vim, visual studio.. 로 작성)

*.o (목적파일) -> 기계가 이해하는 언어 (gcc compiler 필요) 

a.out (실행파일) -> 기계어와 라이브러리를 링크해서 실행파일을 만들어준다.

*.c => *.o => a.out : 컴파일 과정 

 

기존 실행파일 만들어지는 과정

1. 함수를 가지고 있는 .c 파일을 여러개 생성한다.

2. .h 헤더파일을 생성해서 해당 함수들의 원형을 넣어준다.

3. #include "~.h" 로 각각의 .c 파일에 헤더파일을 포함해준다.

4. 목적파일 .o를 만드는 방법 : gcc -c *.c 옵션으로 .o 파일이 만들어진다.

5. 실행파일 만드는 방법 : gcc -o 실행파일명(기본값 : a.out) 목적파일(*.o)

(목적파일을 넣는 대신 바로 .c 파일들을 넣어줘도 실행파일이 만들어진다. 다만 목적파일이 안만들어진다.

 

Makefile의 일반적인 모양

TARGET : DEPENDENCY

    command

 

TARGET 을 만들기 위해서는 DEPENDENCY 가 필요하다.

(불필요시 DEPENDENCY를 적지 않아도 된다.)

command 를 통해서 TARGET을 생성하는 코드를 작성한다.

 

 기본 예시 (Makefile)

all : app.out

app.out : main.o doyou.o coding.o
	gcc -o app.out main.o doyou.o coding.o

main.o :
	gcc -c main.c

doyou.o :
	gcc -c doyou.c

coding.o :
	gcc -c coding.c

 

이렇게 작성해서 Makefile을 만들면, make를 shell에 입력하면 app.out이 만들어진다.

(또한, main.o, doyou.o, coding.o 파일도 다 만들어진다.)

 

여기서 특히 all 부분을 꼭 작성해야 하는데, 그렇지 않으면 첫번째 TARGET만 실행하고,

만약 app.out 이 가장 아래 있으면 원하는 실행파일을 만들지 못하게 된다.

 

환경변수 선언 활용 1 (CC, TARGET)

CC = gcc
TARGET = app.out

all : $(TARGET)

main.o :
	$(CC) -c main.c

doyou.o :
	$(CC) -c doyou.c

coding.o :
	$(CC) -c coding.c

$(TARGET) : main.o doyou.o coding.o
	$(CC) -o $(TARGET) main.o doyou.o coding.o

 

우선 환경변수는 '='으로 변수에 원하는 코드를 작성해서 대입하면 된다.

CC에는 gcc, TARGET에는 app.out 을 넣었는데, 해당 코드가 들어가던 자리에,

$()를 넣게 되면 기존과 동일하게 동작한다. 그리하여, 환경변수에 들어가는 값만 바꿔주면

전체 코드를 다 수정할 필요가 없어 수정에 용이한 상태가 된다. 예를 들어, 컴파일러가 gcc가 아니라 cc 이거나,

TARGET이 app.out 대신 a.out으로 사용할 수 있는데 이를 각각 한 부분만 수정하여 쉽게 바꿀 수 있다.

 

환경변수 선언 활용 2 (OBJS, @, ^)

CC = gcc
TARGET = app.out
OBJS = main.o doyou.o coding.o

all : $(TARGET)

$(TARGET) : $(OBJS)
	$(CC) -o $@ $^
    
main.o :
	$(CC) -c main.c

doyou.o :
	$(CC) -c doyou.c

coding.o :
	$(CC) -c coding.c

 

*.o 파일도 한번에 환경변수 (OBJS) 로 모아서 사용하는 것이 편하다.

그리고, TARGET 과 DEPENDENCY 는 각각 @와 ^로 대응할 수 있다. (중복을 줄여줌.)

 

환경변수 선언 활용 3 (.c.o)

CC = gcc
TARGET = app.out
OBJS = main.o doyou.o coding.o

all : $(TARGET)

$(TARGET) : $(OBJS)
	$(CC) -o $@ $^

.c.o :
	$(CC) -c -o $@ $<

 

.c.o 에서 @는 .o를 의미하고, <는 .c를 의미하여, 기존에 모든 .o 마다 적용하던 것을 간추렸다.

 

환경변수 선언 활용 4 (CFLAGS, LDFLAGS)

CC = gcc
TARGET = app.out
OBJS = main.o doyou.o coding.o

CFLAGS = -Wall
LDFLAGS = -lc

all : $(TARGET)

$(TARGET) : $(OBJS)
	$(CC) $(LDFLAGS) -o $@ $^

.c.o :
	$(CC) $(CFLAGS) -c -o $@ $<

 

CFLAGS 는 컴파일 옵션을 적용할 때, LDFLAGS는 링크 옵션을 적용할 때 사용한다.

 

추가 구현 (clean)

clean :
	rm -f $(OBJS) $(TARGET)

 

clean 과 같은 구현으로, 코드를 용이하게 줄여서 사용할 수 있다.

 

 

+)

make 한 상태에서 내부의 함수가 수정 되었을 때, 해당 바뀐 파일만 컴파일 해준다.

규모가 커질수록 Makefile이 중요한 이유이다.

'프로그래밍 > Linux' 카테고리의 다른 글

[study] LVM(Logical Volume Manager) 절차 정리  (0) 2024.04.12
Recent Posts
Popular Posts
Recent Comments