2018년 11월 24일 토요일

Makefile

GNU Make


리차드 스톨만이 개발한 빌드 시스템



빌드 및 설치, 배포 전 과정을 makefile 에 담을 수 있음
Shell 명령 기반으로 인해 특정 언어 또는 빌드 작업에 활용도가 국한되지는 않음


예제 코드

Makefile


make 명령은 폴더에 Makefile 이 존재하는지 확인하고 Makefile에 정의된 동작을 수행한다

Makefile 구성


Makfile 은 target 선언부와 변수 선언부로 나뉜다

Target 과 명령 세트


Target 은 실행 단위이며 make all 또는 make clean 등의 all 또는 clean 에 해당한다

예)
all:
    gcc -o app main.c


설명:

  • all 은 target 이름 이고 gcc -o app main.c 는 명령
  • 명령문을 입력하지 않아도 되며 아무 동작하지 않는 target 이 됨
  • 명령문은 반드시 탭 '\t' 문자열로 시작
  • 명령문은 일반 shell 명령문이며 빌드와 관련 없을 수도 있음
  • 하나의 target 에 여러 명령문 작성시 순차적으로 수행
  • shell prompt 에서 make all 로 명령문 수행
  • Makefile 의 기본 target 은 all

Target


<target name>: [<depend target name> [<depen target name> ...]]
    [<command>
    [<command>]]


Target 이름

  • Makefile 은 target 이름을 기본적으로 파일명으로 간주
  • 폴더에 target 이름의 파일이 이미 존재하는 경우 해당 target 의 명령은 수행하지 않고 다음 동작을 이어감
    • 빌드 시간 단축을 위함
    • Target 이름을 파일로 간주하지 않도록 하는 기능이 존재함 (아래 설명)

의존성

  • Target 이름에 depent target 들을 열거하여 해당 target 수행 전에 선행되어야 할 target 들을 명시

예)
all: hello

hello:
    gcc -o hello hello.c


    • all target 은 hello target 을 의존하며 make all 수행시 hello target 이 먼저 선행되고 all 이 수행됨


Target 이름을 파일 이름 취급에서 제외

.PHONY: all clean

  • all 과 clean target 의 명령셋은 파일중에 all, clean 이라는 파일명이 있어도 수행


Pattern target name

  • 대체로 .c 파일은 .o 파일로 컴파일되는 파일명 상 규칙이 존재하는 경우 pattern 명 을 활용하여 일괄 적용 가능 
예) 
OBJS = a.o b.o

all: hello

hello: $(OBJS)
    gcc -o $@ main.c $(OBJS)

%.o: %.c
    gcc -c -o $@ $<

clean:
    rm -rf hello $(OBJS)

    • %.oa.o 또는 b.o target 을 호출할 때 수행되며 %.c 의존성은 a.oa.cb.ob.c 로 매핑
    • $@$< 은 예약어
      • $@ : %.o 가 expand 된 값으로 예제에서는 a.o 또는 b.o
      • $< : %.c 가 expand 된 값으로 예제에서는 a.c 또는 b.c
    • make 시 아래 명령들이 수행됨
gcc -c -o a.o a.c
gcc -c -o b.o b.c


명령문


  • 명령문은 일반 shell 명령
  • Makefile 은 명령문 한줄 한줄 실행할 때 마다 새로운 shell 을 열기 때문에 이전 명령문의 상태를 이어가지 않음

예)
all:
    mkdir -p temp
    cd temp
    touch a
    ls temp/a

    • 예상하기로 마지막 명령에 ls temp/a 가 성공해야 할 것 같지만 실패함
    • cd temp 가 다음 명령까지 이어가지 않기 때문

  • 일반적 해결 방법

all:
    mkdir -p temp
    cd temp && touch a
    ls temp/a

    • 여러 명령이 상태를 이어갈 필요가 있는 경우 한줄에 명령들을 표기
    • 여러 명령을 같은 환경 아래서 동작하게 하기 위해 && 연결 기호를 사용

변수


  • 변수는 Makefile 내 선언과 환경 변수가 복합
  • Makefile 내 선언
예)
var := hello

all:
    @echo $(var)
    • make 수행 시 hello 를 출력

  • 환경 변수
예)
all:
    @echo $(PATH)

    • PATH 환경 변수 자동으로 변수로 등록

  • 선언 우선순위


예)
VAR1 := var1
VAR2 ?= var2

print:
    echo $(VAR1)
    echo $(VAR2)


$ make print
echo var1
var1
echo var2
var2
$ VAR1=yyy make print
echo var1
var1
echo var2
var2
$ VAR2=yyy make print
echo var1
var1
echo yyy
yyy

    • VAR2 는 VAR1 과 다르게 make 수행 전에 설정된 변수를 따름
  • 변수 expand
    • expand 시간이 달라짐
      • ':=' 선언시
      • '=' 호출시

예)
MYVAR = "my var!"
IMMEDIATE := $(MYVAR)
LAZY = $(MYVAR)
MYVAR = "new my var!"


print:
        @echo "MYVAR is '$(MYVAR)'"
        @echo "IMMEDIATE is '$(IMMEDIATE)'"
        @echo "LAZY is '$(LAZY)'"


$ make print
MYVAR is 'new my var!'
IMMEDIATE is 'my var!'
LAZY is 'new my var!'

GNU 표준 디렉토리


프로그램 설치시 GNU 표준 디렉토리 규정에 따라 목적에 맞는 위치에 파일들을 복사


댓글 없음:

댓글 쓰기