본문 바로가기
OS/Linux

[Linux/C] Makefile

by dev_Step 2022. 5. 19.

 

Linux 에서 컴파일을 할때 gcc 를 통해서 컴파일을 진행했다

 

gcc 의 옵션들을 사용해서 컴파일 했었는데

옵션으로 

-c : 의경우는 .c 파일을 통해서 ~~.o 인 오브젝트 파일을 만들때 사용했었다

 ex) gcc -c main.c --> main.o 가 생성됨 // 동일한 방법으로 gcc -c -o main.o main.c 

   --> main.c 파일을 통해 main.o 파일을 생성하였다 -o 옵션으로 원하는 파일명으로 만들수 있다

 

gcc main.c 의 경우는 

 a.out 이라는 이름의 실행 파일이 생성되어 진다.

 

gcc -o test main.c 의 경우는

  test 라는 이름으로 실행 파일이 생성되어 진다.

 

여러개의 파일을 묶어서 컴파일 할경우는 소스파일들을 나열하여 진행했다

gcc main.c sum.c --> -o 옵션을 사용하지 않았기 때문에 a.out이라는 실행 파일이 생성되었다.

gcc -o test main.c sum.c 이를 통해 test라는 실행파일이 생성되었다.

 

 

그렇다면 만약에 컴파일 시에 100개 1000개의 파일을 한번에 컴파일 하려면 어떻게 해야할까?

 gcc -o test main.c source.c source1.c source2.c source3.c source4.c 이렇게 100개 1000개를 적어야 할까?

 

이때 Makefile를 사용하면 된다. Makefile 이란 make 라는 유틸리티를 사용하여 여러개의 복합적인 컴파일을 쉽게 할수 있도록 도와주는 것으로

vi Makefile  --> 을 통해서 생성하면되고 

Makefile의 양식으로는 아래와 같다.

목적파일에는 : 실행파일(최종 실행하고자 하는 실행파일), 오브젝트파일(.o), 라이브러리(.a) 등이 올수있고

의존성에는 : 목적파일을 생성하기위해서 필요한 파일을 넣어준다 (.o)

명령어는 : 해당 목적파일을 생성하기 위한 명령어를 넣어준다.

다음과 같다.

all : --> test 가 생성될때 까지 실행한다는 것으로 test 실행파일을 만들기위한게 목적이라는 말로 이해했다.

다음줄 : test : main.o sum.o   -->  test 라는 실행파일을 만들기 위해서는 main.o, sum.o 파일이 필요하다는 의미

다음줄 : test 를 만들기 위한 명령어가 적혀있다

 

동일하게 main.o // sum.o 파일을 만들기 위해서는 main.c // sum.c 라는 파일이 필요하고

해당 파일을 생성하기 위한 명령어가 있다.

 

마지막으로 clean 을 볼수 있는데 여기서는 의존성이 존재하지 않는데

make 파일에서    의존성이 비어있는 경우는

make 라는 명령어를 통해서 해당 문장이 실행되지 않고

make clean <-- 이렇게 해당 명령어를 직접 붙여줘야 실행되고

의존성이 있는경우는 make <-- 라는 명령어에 자동적으로 실행된다.

make 라는 명령어로  Makefile 에 적은 것들이 자동적으로 실행되어 test라는 파일이 생성되고

make clean이라는 명령어로  .o 파일과 test 파일이 삭제된것을 확인할 수 있다.

 

여기서 Makefile을 더 간결하게 사용하는 방법은 없을까 라는 의문이 들것이다. 당연히 있다

Makefile의 명렁어를 한번 알아보자

 

여러가지 문자들이 변환된것을 확인할 수 있는데

맨위에 변수명 = 값  <--- 으로 선언된 것을 확인할 수 있는데 

 

= 으로 선언되어 있는 변수명들은

$(변수명) <-- 으로 사용할수 있다 

그래서 현재 $(EXE), $(OBJS), $(CC) 등으로 사용된것을 확인할 수 있다.

$^ 의 경우는 의존성을 그대로 가져다 쓸수 있다. 즉  $(OBJS)-에 있는 값인 main.o sum.o 가 된다.

 

여기서 한번더 간결하게 바꾸자면

$@ 이 추가되었는데 이 표현은  목적파일의 값을 그대로 가져와 사용할때 사용할수 있다

아래보면 $(EXE)의 값과 $(CC) -o test $^ 에서 test 값과 $(EXE) 값이 동일하므로 $@ 으로 바꿔서 표현했다

 

더 내용을 추가해 보자면

우선 가장 상단에 CROSS 라는 변수를 선언했는데 해당 변수를

CC에서 사용하고 있다 

이것은 gcc 컴파일러를 arm-gcc 라던지 다른 gcc를 사용할 경우에 CROSS에 값만 추가하여 사용하면

크로스 컴파일을 할때 원활하게 할 수 있도록 사용한다고 한다.

DEFINE 의 경우는 해당 파일에 #ifdef 되어 있는 값이 맞게 컴파일을 하고 싶을때 사용하는 것으로

주로 CFLAGS에 추가하여 사용한다.

CFLAGS는  gcc 컴파일러의 옵션을 추가할떄 사용하는 변수명이다.

 -> 현재 CFLAGS에는 -I 옵션이 추가되어 있는것을 확인할 수 있다

 -> -I 다른 폴더에 있는 헤더파일을 참조 할 수 있도록 해준다. 

DEFINE의 값에 따른 컴파일 결과가 다른것을 확인할 수 있다...

 

 

 

마지막으로  OBJS 에서 만약에  오브젝트 파일인 .o 파일이 다수일경우는 하나씩 써주기 힘드므로 

와일드 카드라는 값을 사용해주면 쉽게 오브젝트 파일을 사용할 수 있다.

 

OBJS 는 주석처리하였고

C_SRC= $(wildcard *.c) 가 추가 되었는데 이 의미는

  -> 현재 디렉토리에서  .c 로 끝나는 모든파일을 C_SRC에 넣는다는 의미로 결국

  -> C_SRC = main.c sum.c 와 동일하다

OBJ= $(C_SRC:.c=.o) 이 의미는 

  -> C_SRC에 있는 .c 파일들을 모두 .o 로 바꾸라는 의미이다. 즉

  -> OBJ = main.o sum.o 이 된다.

 

또한 와일드 카드로 사용되어 C_SRC= $(wildcard *.c), OBJ= $(C_SRC:.c=.o) 

으로 표현되었으므로 만약에 새로운 .c 파일이 생성되더라고 컴파일시에 자동으로 추가되어 

컴파일 해준다.

Makefile에서 와이드 카드를 설정한 후에 sum2.c 파일을 생성한다음에 

make를 진행하면 자동으로 sum2.c 가 포함되어    sum2.o sum.o main.o 로 컴파일된것이 확인되어진다.

 

'OS > Linux' 카테고리의 다른 글

[Linux/C] 파일 입출력1-1(표준입출력)  (0) 2022.05.25
[Linux/C] 파일 입-출력2  (0) 2022.05.25
[C/Linux] 헤더 파일  (0) 2022.05.16
[Linux/C] GDB  (0) 2022.03.25
[Linux/C] 함수 포인터  (0) 2022.03.24