Makefile

참고
[1] https://www.tuwlab.com/ece/27193


Makefile

  • C++ 파일을 빌드하는 명령어가 담긴 쉘 스크립트 파일이다.
  • make 명령어를 통해 실행할 수 있다.
  • C++ 파일의 컴파일은 많은 헤더 파일, 소스 파일의 빌드와 링크로 하나의 실행파일을 만들어 내기 때문에 많은 빌드와 링크 명령어를 입력해야 한다. 터미널에 입력하고 실행하는 과정에서 여러 명령어를 실행하기 때문에 가시성과 정확성이 떨어질 수 있고, 파일의 중복 저장 같은 하나의 명령어 실수가 치명적으로 다가올 수도 있다. 그렇기 때문에 쉘 스크립트에 명령어를 저장하고 실행하는 것은 안전성과 편리성, 가시성 등등 모든면에서 이점이 있다.
  • Makefile의 기본적인 구조는 다음과 같다. Target은 빌드 대상, Dependecies는 빌드 대상이 의존하는 Target이나 파일들, Recipe는 빌드 대상을 생성하는 명령어를 의미한다.
  • 순수히 make 명령어를 입력하면 Makefile에 있는 모든 명령어가 실행되고, make kernel.out 이나 make kernel.o 의 명령어를 입력하여 특정 Target만을 생성할 수 있다.
    Target: Dependencies
        Recipe
    
    kernel.out: kernel.o
      nvcc -o kernel.out kernel.o
     
    kernel.o: kernel.cu
      nvcc -c -o kernel.o kernel.cu
    

변수 사용하기

  • Makefile 내에서도 변수를 지정 및 사용할 수 있다.
  • 변수는 = 를 통해 정의할 수 있고, $() 구문을 통해 사용할 수 있다.
  • CC: 컴파일러
  • CFLAGS: 컴파일 옵션
  • OBJS: 중간 산물 Object 파일 목록
  • TARGET: 빌드 대상(실행 파일) 이름
  • LDFLAGS: 링커 옵션
  • LDLIBS: 링크 라이브러리
  • $@: 현재 Target 이름
  • $^: 현재 Target이 의존하는 대상들의 전체 목록
  • $?: 현재 Target이 의존하는 대상들 중 변경된 것들의 목록
  • clean: make 명령어를 실행 후 실행되며, 부산물을 삭제할 때 사용한다.
    CC=nvcc
    OBJS=kernel.o
    TARGET=kernel.out
     
    clean:
      rm -f kernel.o
     
    $(TARGET): $(OBJS)
      $(CC) -o $@ $(OBJS)
     
    kernel.o: kernel.cu
      $(CC) -c -o $@ kernel.cu
    

통상적인 포멧

  • all은 해당 타겟을 만들어 내겟다 라는 의미인 것 같다.
    CC=<컴파일러>
    CFLAGS=<컴파일 옵션>
    LDFLAGS=<링크 옵션>
    LDLIBS=<링크 라이브러리 목록>
    OBJS=<Object 파일 목록>
    TARGET=<빌드 대상 이름>
     
    all: $(TARGET)
     
    clean:
        rm -f *.o
        rm -f $(TARGET)
     
    $(TARGET): $(OBJS)
    $(CC) -o $@ $(OBJS)