2022-06-05 Makfile_이해

2022. 6. 5. 22:02BE/Linux

make, Makefile 이해



gcc

 

C언어의 컴파일 과정

 

  1. 전처리기 : #으로 시작하는 전처리 구문을 처리
gcc -E test.c -o test.i
  1. 컴파일러 : 고급언어를 저급언어로 번역
gcc -S test.i -o test.s
  1. 어셈블러 : 저급언어를 기계어로 번역
gcc -c test.s -o test.o
  1. 링커 :
gcc test.o -o test.exe

 

-o : 생성 된 파일의 이름을 지정

 

출처 : https://reakwon.tistory.com/52


make

 

지금부터 작성한 글은 아래 포스트를 많이 참고해서 작성했습니다.

 

출처 : https://bowbowbow.tistory.com/12#make-와-makefile

 

파일이 많으면 컴파일하기 힘들다.

 

컴파일 및 관리를 편하게 하기 위해서 Makefilemake를 이용한다.

 

Makefile에 컴파일 및 관리를 수행하는 방식을 규정하고 make 명령어로 실행한다.

 

Makefile의 구성

-목적파일(Target) : 명령어가 수행되어 나온 결과를 저장할 파일

-의존성(Dependency) : 목적파일을 만들기 위해 필요한 재료

-명령어(Command) : 실행 되어야 할 명령어들

-매크로(macro) : 코드를 단순화 시키기 위한 방법
CC = gcc // 매크로 정의

// 타겟 : 의존성 의존성
target1 : dependency1 denpendency2
	command1 // 명령어
	command2
target2 : dependency3 denpendency4
	command3
	command4
매크로 정의 

목표파일 : 목표파일을 만들기 위해서 필요한 구성요소들 (dependency는 없어도 된다.)
(tab)목표 달성을 위한 명령1
(tab)목표 달성을 위한 명령2

길이가 긴 공백은 tab를 사용한다.


예시

 

//diary.h

#include<stdio.h>
void memo();
void calendar();
//meno.c
#include "diary.h"
void memo(){
	printf("memo func \n");
}
//calendar.c
#include "diary.h"
void calendar(){
	printf("calendar func \n");
}
//main.c
#include"diary.h"
int main(void){
	memo();
	calendar();
	return 0;
}

 

gcc 명령어 사용

gcc -c -o memo.o memo.c
gcc -c -o calendar.o calendar.c
gcc -c -o main.o main.c
gcc -o diary_exe main.o memo.o calendar.o

# 혹은

gcc -o diary_exe memo.c calendar.c main.c

 

make 명령어 사용

vim Makefile

# 대문자 M 사용.
diary_exe : memo.o calendar.o main.o
	gcc -o diary_exe memo.o calendar.o main.o

memo.o : memo.c
	gcc -c -o memo.o memo.c

calendar.o : calendar.c
	gcc -c -o calendar.o calendar.c

main.o : main.c
	gcc -c -o main.o main.c

clean :
	rm *.o diary_exe

 

기본적으로 make 명령어를 사용하는 방법은 make [targetName]을 쉘에 입력한다.

$ make diary_exe
gcc -c -o calendar.o calendar.c
gcc -c -o main.o main.c
gcc -o diary_exe memo.o calendar.o main.o
$ make memo.o
gcc -c -o memo.o memo.c
$ make clean
rm *.o diary_exe

make clean : 현재 디렉터리에 있는 object 파일과 diary_exe를 지운다.

 

clean은 더미타겟으로 파일을 생성하지 않는 타겟이다.

 

$ make
gcc -c -o memo.o memo.c
gcc -c -o calendar.o calendar.c
gcc -c -o main.o main.c
gcc -o diary_exe memo.o calendar.o main.o

아무런 targetName 없이 make 명령을 입력했을때는 default target을 생성한다.

 

별도의 default target 지정 없으면 가장 상단에 위치한 target 파일을 생성한다.

 

default target을 지정하는 방법은 아래와 같다.

 

all : diary_exe

따로 가장 상단에 all이라는 타겟을 설정하고 의존성에 정말 우리가 필요한 타겟을 넣으면 된다.

 


Makefile 매크로

 

diary_exe : memo.o calendar.o main.o
	gcc -o diary_exe memo.o calendar.o main.o

memo.o : memo.c
	gcc -c -o memo.o memo.c

calendar.o : calendar.c
	gcc -c -o calendar.o calendar.c

main.o : main.c
	gcc -c -o main.o main.c

clean :
	rm *.o diary_exe

Makefile을 더 단순하게 작성하기 위해서 중복되는 코드를 특정한 단어로 치환한다.

 

이 과정을 매크로라고 한다.

 

짧은 코드면 오히려 복잡하다고 느낄 수 있지만 코드가 길어지고 복잡해질수록 매크로를 사용했을 때 얻을 수 있는 효과가 크다.

 

 

사용할 수 있는 매크로 몇가지와 관용적으로 사용하는 변수 이름을 살펴보자.

 

Option Desciption
$@ 해당 블록의 Target
$^ 해당 블록의 Dependencies 중 전체로 대치됨
$< 해당 블록의 Dependencies 중 첫 번째로 대치됨
$* 확장자가 없는 Target으로 대치됨
$? 해당 블록의 Dependencies 중에 Target보다 새로운 파일들 목록으로 대치됨
Variables Description
CC C compiler, cc, gcc
CXX C++ compiler, g++
CFLAGS Extra flags to give to the C compiler
CXXFLAGS Extra flags to give to the C++ compiler
CPPFLAGS Extra flags to give to the C preprocessor
LDFAGS Extra flags to give to compilers when they are supposed to invoke linker
SRCS Source codes
OBJS Object codes
TARGET Target file
.SUFFIXES 확장자 규칙
INC Include path

이외에도 사용자의 기호에 맞춰 매크로를 설정할 수 있다.

 

매크로 이름은 보통 대문자로 작성한다.

 

$(매크로 이름)로 매크로의 값을 참조할 수 있다.

 

diary_exe : memo.o calendar.o main.o
	gcc -o diary_exe memo.o calendar.o main.o

memo.o : memo.c
	gcc -c -o memo.o memo.c

calendar.o : calendar.c
	gcc -c -o calendar.o calendar.c

main.o : main.c
	gcc -c -o main.o main.c

clean :
	rm *.o diary_exe

 

  1. CC, TARGET, OBJS 정의
CC = gcc
TARGET = diary_exe
OBJS = memo.o calendar.o main.o

all : $(Target)

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

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

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

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

clean :
	rm $(OBJS) $(TARGET)

 

  1. $@, $^ 사용
CC = gcc
TARGET = diary_exe
OBJS = memo.o calendar.o main.o

all : $(Target)

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

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

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

clean :
	rm $(OBJS) $(TARGET)

 

  1. %.o, %.c 사용
CC = gcc
TARGET = diary_exe
OBJS = memo.o calendar.o main.o

all : $(Target)

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

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

clean :
	rm $(OBJS) $(TARGET)

많이 짧아졌다!

 

%.o의 의미는 .o로 끝나는 어떤 파일을 의미한다.

 

%.c는 .c로 끝나는 어떤 파일이고 앞선 %.o와는 확장자를 제외하고 같은 파일이름을 지녔을 것이다.

 

마지막으로 주의할 점에대해 알아보자.

clean :
	rm $(OBJS) $(TARGET)

만약 디렉토리내에 clean이라는 파일이 있으면 정상적으로 Makefile이 작동하지 않을 것이다.

 

이때는 …

clean :
	rm $(OBJS) $(TARGET)

.PHONY : clean

.PHONY : clean을 추가하면 된다.

 

Phony는 '가짜의, 허위의' 이라는 뜻이다.

 

PHONY가 다수라면 옆에 띄어쓰고 열거하면 된다.

 

.PHONY : a b c 

 


Makefile 보충

 

:=, ?=+=는 뭐지?

출처 : https://leehc257.tistory.com/67

 

  • = 사용
T=A
W=$(T)
T=B

run :
	echo $(T)
	echo $(W)
// 결과
$ make
echo B
B
echo B
B

=T=A를 무시한다.

 

=는 어디에서든 상관없이 나중에 작성된 T=B로 일관성을 유지한다.

 

  • := 사용
T=A
W:=$(T)
T=B

run :
	echo $(T)
	echo $(W)
// 결과
$ make
echo B
B
echo A
A

:=T=A를 무시하지 않고 반영하는 것을 알 수 있다.

 

실제 W가 정의된 시점의 TA를 반영했다.

 

  • += 사용
T=A
T+=B

run :
	echo $(T)
// 결과
$ make
echo A B
A B

기존의 문자열에 이어쓰기하는 방식이다.

 

  • ?= 사용

This is called a conditional variable assignment operator, because it only has an effect if the variable is not yet defined.

 

변수가 정의되지않으면 변수의 값을 대입한다.

 


$(OBJS:.o=.d)는 뭐지?

 

$(OBJS:.o=.d) 부분은 OBJS 에서 .o 로 끝나는 부분을 .d 로 모두 대체한다는 뜻이다.

 


Makefile 조건문

 

//같은지 비교하고 싶다면 ifeq ~ else ~endif 사용.
//equal

ifeq ($(CC),gcc)
//같지 않은지 비교하고 싶다면 ifneq ~ else ~ endif 사용.
//not equal
ifneq ($(CC),gcc)
//매크로가 정의되었는지 되지 않았는지에 따라 Makefile을 다르게 구성하고 싶다면 
//ifdef ~ else ~ endif 또는 ifndef ~ else ~ endif 사용.
//define? not define?

ifdef CC
ifndef CC

Makefile 함수

 

$(shell 쉘 명령어)

shell 명령에 대한 결과를 저장한다. $(변수명) <- 이 자리에 해당 결과가 들어가는 셈이다.

이것말고도 엄청나게 많은 함수를 지원한다.

 

필요하면 찾아서 사용하자.

 


참고