Love Every Moment

〔Linux/Unix〕Makefile 이란? 메이크 파일 작성하는 방법 본문

PROGRAMMING::CORE/Operating System

〔Linux/Unix〕Makefile 이란? 메이크 파일 작성하는 방법

해 송 2021. 6. 1. 18:16
반응형

1. Makefile 이란?

 

  • Make: 주어진 쉘 명령어들을 조건에 맞게 실행하는 프로그램
  • Makefile: 어떤 조건으로 명령어를 실행할지 담은 파일
  • Incremental build: 반복적인 빌드 과정에서 변경된 소스코드에 의존성(Dependency)이 있는 대상들만 다시 빌드
  • 예: main.c의 한 줄만 바꾸고 다시 빌드한다면 main.o 컴파일(gcc -c -o main.o main.c)과 a.out링크(gcc -o a.out main.o foo.o bar.o)만 수행

 


 

2. 소스 코드에서 프로그램 빌드하기

 

(1) 컴파일(Compile)

  • 소스 코드를 컴퓨터가 이해할 수 있는 어셈블리어로 변환하는 과정
  • -c 옵션: 링크를 하지 않고 컴파일해서 목적 파일(Object File)을 생성하라는 의미
  • -o 옵션: 생성된 아웃풋 파일의 이름을 지정하는 옵션
$gcc -c -o main.o main.c
$gcc -c -o foo.o foo.c
$gcc -c -o bar.o bar.c

 

기타 gcc 옵션
    • -g: 디버그 정보 포함
    • -L: 헤더 파일의 디렉토리, 즉 -l 로 지정된 라이브러리가 존재하는 위치를 알려준다
    • -l: 라이브러리 지정, 즉 특정한 라이브러리(.a)를 포함하도록 알려준다
      • 예를 들어, libabc.a 라는 라이브러리 파일을 링크시키려면 -labc 로 옵션을 준다.
    • -I: 컴파일러가 #include 가 작성된 라인에 있는 헤더파일의 위치를 찾을 수 있게 위치를 알려준다.
      • 일반적으로, C에서    #include <stdio.h>    #include "maru.h"
      • 이런식으로 헤더를 사용하는데 < > 안에 사용한 경우는 /usr/include (시스템 표준 헤더 디렉토리) 를 기준으로 찾아서 가지고 오는 것이고 " " 안의 경우는 현재 컴파일러가 실행되는 현재 디렉토리를 기준으로 가지고 오는데 이와 같지 않은 경우에 사용하는 것이 -I 옵션이다.
    • -Wall: 모든 경고 표시
    • Werror: 모든 경고를 에러로 처리
    •  
 

What is the difference between -I and -L in makefile?

What is the usage of the -I and -L flags in a makefile?

stackoverflow.com

 

 

(2) 링크(Link)

  • 서로 다른 파일에 흩어져 있던 함수나 클래스들을 한 데 묶어서 링크해주는 작업
  • main 함수 안에 foo 함수와 bar 함수가 어디에 정의되어 있는지 위치를 찾고 제대로 함수를 호출할 수 있게 된다
gcc main.o foo.o bar.o -o a.out

 


 

3. Makefile 매크로

 

(1) make -p: Makefile 에서 미리 정의된 매크로 확인

매크로 이름 설명 기본값
AR 아카이브 관리 프로그램  ar
AS 어셈블러 as
CC C 컴파일러 cc
CXX C++ 컴파일러 g++
CPP C 전처리기 cc -E
LD 링크 ld
ARFLAGS AR 플래그  
ASFLAGS 어셈블러 플래그  
CFLAGS C 컴파일러 플래그  
CXXFLAGS C++ 컴파일러 플래그  
CPPFLAGS C 전처리기 플래그  

 

(2) make 내부적으로는 정의되어 있지만, make -p로 확인할 수 없는 자동 매크로

make 내부적으로는 정의되어있지만, make -p로 확인할 수 없는 자동 매크로
$?
현재 타겟보다 최근에 변경된 종속 항목 리스트
$^ 현재 타겟의 종속 항목 리스트
$@ 현재 타겟의 이름
$< 현재 타겟보다 최근에 변경된 종속 항목 리스트
$* 현재 타겟보다 최근에 변경된 종속 항목의 이름
$% 현재 타깃이 라이브러리 모듈일 때 .o 파일에 대응되는 이름

 

 


 

4. 아카이브 생성

ar crus [라이브러리 이름] [오브젝트 파일들]

 

(1) c 옵션: 아카이브 파일이 존재하지 않아도 경고 메시지를 출력하지 않음.

(2) r 옵션: 새로운 오브젝트 파일이면 추가, 기존 파일이면 치환함.

(3) u 옵션: 오브젝트 파일의 타임스탬프를 비교해 새로운 파일일 경우에만 치환함.

(4) s 옵션: ranlib(1)과 마찬가지로 아카이브 인덱스를 생성.

→ 아카이브 인덱스를 생성하지 않으면 링크 속도가 느려지고 시스템 환경에 따라서는 에러가 발생한다.

 


 

5. Makefile 의 구성 

[Target] : [...Dependencies...]
                 [...Recipes...]

 

(1) 타겟(Target)

  • make 의 대상: 무엇이 make 를 통해 최종적으로 만들어지는가?
  • 예: make a.out   make libft.a   make all

 

(2) 의존 파일(Dependency)

  • 주어진 타겟을 make 할 때 사용되는 파일들의 목록
  • 필요 조건(Prerequisites)이라고도 부른다
  • 해당 타겟을 처리하기 위해 건드려야할 파일들
  • 만일 주어진 파일들의 수정 시간 보다 타겟이 나중에 수정되었다면 해당 타겟의 명령어를 실행하지 않는다.
  • 이미 이전에 타겟이 만들어져있다고 간주하기 때문이다.

 

(3) 레시피(Recipes)

  • 주어진 타겟을 make 할 때 실행할 명령어들의 나열
  • 반드시 탭 한 번으로 들여쓰기를 해줘야 한다.
foo.o : foo.h foo.c
             gcc -c foo.c

bar.o : bar.h bar.c
             gcc -c bar.c

main.o : main.c foo.h bar.h
             gcc -c main.c

a.out : foo.o bar.o main.o
             gcc foo.o bar.o main.o -o a.out

 


 

7. Makefile 작성하기

TARGET = a.out
CC = gcc
CFLAGS = -Wall -Wextra -Werror
AR = ar rcs
RM = rm -f

FILES = foo \
               bar \
               main

SRCS_DIR = ./
SRCS = $(addprefix $(SRCS_DIR), $(addsuffix .c, $(FILES)))

OBJS_DIR = ./
OBJS = $(addprefix $(OBJS_DIR), $(addsuffix .o, $(FILES)))

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

$(NAME): $(OBJS)
$(AR) $@ $^

all: $(NAME)

clean:
$(RM) $(OBJS)

fclean: clean
$(RM) $(NAME)

re: clean all

.PHONY: all clean fclean re

 


 

8. 기타 설명

 

(1) 클린(Clean) 매크로

  • rm -f
  • 빌드 결과물(ex. a.out)과 중간 부산물들(*.o )을 모두 삭제하여 '깨끗한' 상태에서 다시 빌드할 수 있는 환경을 만들어준다.
  • 이것을 클린 빌드(Clean build)라고 한다.

 

(2) 헤더파일 경로

  • INCLUDE = -Iinclude/ 
  • 헤더파일만 모아서 디렉터리에 저장했을 경우에 사용

 

(3) .PHONY

  • 기존에 해당 이름의 파일이 존재하는지 확인하지 않고 make 명령어를 실행
  • ex) "clean" 이라는 이름의 파일이 이미 존재하더라도 make clean 명령어를 실행하게 한다.

 

 

References:

 

씹어먹는 C++ - <19 - 1. Make 사용 가이드 (Makefile 만들기)>

 

modoocode.com

 

Makefile 만들기

Makefile을 사용하는 이유는 위와 같은 복잡한 과정을 생략할 수 있어서이기도 하지만, Makefile이 제공하는 강력한 기능 중 하나인 Incremental build 를 사용하기 위해서다.

velog.io

 

gcc와 makefile

회사에서 사용하는 makefile을 가지고 다른 곳에서 작업을 했는데 많은 오류들이 생겨서 makefile에 대한 ...

blog.naver.com

 

컴퓨터 코딩 프로그래밍

반응형
Comments