290 likes | 624 Views
Makefile 의 이해. ㈜ FALinux http://www.falinux.com 박진호. 목차. make 의 개요 Makefile 의 내부구조 make 구문의 기본 규칙 매크로 확장자 규칙 include 의존관계 프로젝트 관리 Makefile 예제 Makefile 작성 가이드 라인. make 에 대한 개요 (1). make 는 명령을 생성하는 유틸리티 이다 . make 는 기술파일 (Makefile 또는 makefile) 을 이용하여 , 쉘명령을 자동으로 수행하게 한다 .
E N D
Makefile의 이해 ㈜FALinux http://www.falinux.com 박진호
목차 • make 의 개요 • Makefile의 내부구조 • make 구문의 기본 규칙 • 매크로 • 확장자 규칙 • include • 의존관계 • 프로젝트 관리 • Makefile 예제 • Makefile 작성 가이드 라인
make에 대한 개요(1) make는 명령을 생성하는 유틸리티 이다. make는 기술파일(Makefile 또는 makefile)을 이용하여, 쉘명령을 자동으로 수행하게 한다. 소프트웨어 개발 시 반복적 작업을 쉽고, 간단하게 수행 할 수 있게 한다.
make에 대한 개요(2) make는 재작성 시간을 최소화 하여, 작업 시간을 줄여 준다. make는 대규모 소프트웨어 개발시 의존성을 추적하여 여러 사람이 동시에 개발 시 편하고 빠른 개발 환경을 구축 할 수 있게 해준다.
Makefile의 내부 구조(1) • 콜론(:) 을포함하는 행 • 콜론 왼쪽은 타겟 • 콜론 오른쪽은 타겟에 필요한 Dependency • 탭(Tab) 문자로 시작하는 하나이상의 명령 행 • 실제 수행하는 명령을 쓴다.
Makefile의 내부 구조(2) Target: Dependency [TAB] Command • Makefile의 기본적인 형태 • Target • 명령이 수행되어 나온 결과를 파일을 지정. • Dependency • Target이 어떤파일에 종속적인가를 지정. • Command • 실제 실행될 명령어 및 쉘 스크립트 사용가능.
Makefile의 내부 구조(3) Lable: [TAB] Command • 레이블의 사용 • Lable • Target 대신에 사용 가능. • ex) all: • ex) clean: • Command • 실제 실행될 명령어 및 쉘 스크립트 사용가능.
make 구문의기본 규칙 • 빈 라인은 무시 한다. • 라인에 ‘#’이 나오면 그이후로 끝까지 무시 • 하나의 라인이 길어 질 경우 '\'를 추가하여 라인을 바꿀 수 있다. • 라인 사이가 '\' 로 연결된 것은 make에서 하나의 라인으로 인식한다.
매크로(1) INCLUDE = -I/usr/include INCLUDE += -I/usr/locla/include 실제 INCLUDE가 를 참조하여 사용될때는 -I/usr/include -I/usr/locla/include 와 같이 된다. 매크로 작성은 등호를 이용 작성된 매크로를 참조 하기 위해서는 매크로 이름 앞에 ‘$’를 붙여 사용 기존에 작성된 매크로에 내용을 추가 하기 위해서는 += 과 같은 방식을 사용
매크로(2) ‘=‘ 표시 이후에 아무런 문자열이 없는 매크로 정의에는 NULL 문자열이 할당된다. 매크로를 정의하지 않고 사용할 경우 NULL문자열로 치환한다. 매크로 정의 순서는 상관 없다. 같은 이름으로 매크로를 정의하면 맨 마지막에 정의한 매크로만을 참조 한다.
매크로(3) • 미리 정의 해놓은 매크로 및 환경변수 • make 는 수많은 일반 명령들을 매크로로 미리 정의해 놓고 있다. • $(CC) 매크로는 항상 C 컴파일러로 인식. • $(LD) 매크로는 항상 링커로 인식. • make –p 를 이용하여 내부적으로 정의된 매크로가 어떤것이 있는지 출력해서 살펴 볼 수 있다.
매크로(4) $ maketest DIR=/usr/project $ maketest DIR=“/usr/project /usr/project/lib” $ DIR=/usr/project maketest • 명령행에서의 매크로 • make 명령 행에서 매크로를 정의 할 수 있다. • 명령행에서 정의가 여러 단어들로 구성 되어 있을 경우 해당 부분을 작은 따옴표(‘’)나큰 따옴표(“”)로묶어 주어야 한다. • 매크로를 make 명령 이전에 정의 할 수도 있다.
매크로(5) 매크로 할당 우선순위 1. 명령 행에서 정의한 매크로 2. Makefile에 정의된 매크로 3. 현재 쉘의 환경변수 4. make 내부에 정의된 매크로
매크로(6) main.o : io.hmain.c [TAB] gcc –c $*.c main.o : io.hmain.c [TAB] gcc –c $< • 내부 매크로 • 임의로 설정 해서 사용할 없는 매크로 • $* • 현재 타겟보다 최근에 변경된 현재 필요 항목의 이름(확장자 제외) • $< • 현재 타겟보다 최근에 변경된 현재 필요 항목의의 이름(소스파일)
매크로(6) test : main.ofoo.obar.o [TAB] gcc –o $@$*.c test : main.ofoo.obar.o [TAB] gcc –o $@$^ • $@ • 현재 타겟의 이름 • $^ • 현재 타겟보다 최근에 변경된 필요 항목들의 리스트
확장자 규칙(1) make가 파일의 확장자를 보고, 그에 따라 적절한 연산을 수행시키는 규칙 어떤 확장자에 대한 규칙이 정의되어 있더라도, .SUFFIXES 리스트에도 함께 정의 되어야 효력이 있다.
확장자 규칙(2) .SUFFIXES: .out .a .ln .o .c .cc .C .cpp .p .f .F .r .y .l .s .S .mod .sym .def .h .info .dvi .tex .texinfo .texi .txinfo .w .ch .web .sh .elc .el • .SUFFIXES와 우선순위 • 오브젝트 파일이 존재하지 않으면, make는 이를 작성하기 위한 .c, .s 소스 파일을 찿는다. • make는 .SUFFIXES 리스트의 확장자 순서에따라 파일을 검색 한다. • 내부에 미리 정의되어 있는 확장자 리스트
확장자 규칙(3) .c.o: [TAB] $(CC) –c $< -o $@ • 확장자 규칙에 의하여 make는 화일들간의 확장자를 자동으로 인식해서 필요한 작업을 수행한다. • 확장자가 .c 인 파일은 C 소스코드 파일 • 확장자가 .o 인 파일은 오브젝트 파일 • 확장자가 .c 파일은 컴파일 되어 확장자가 .o 파일이 됨
include • include • include는 만드시 줄의 처음에서 시작해야 하면 다음에 공백 문자 혹은 탭문자가 나와야 한다. include 앞에 공백이나 탭이 있어서는 안된다. • include의 효과는 'file_name'의 모든 행을 현재의 Makefile로 옮겨 적는 것과 동일함. • 사용법 • include file_name
의존 관계(1) • 헤더파일 의존성 관계 • make는 소스에 숨겨져 있는 의존관계를 살펴보기 위해 파일의 내부를 들여다 볼 수 없다. • #include 지시자가 소스 파일에 있는지 알 수 있는 방법이 없으므로, 헤더파일이 변경되었을 경우, 다시 오브젝트 파일을 생성할 방법이 없다. • 이러한 한계를 극복하기 위하여 대부분 Makefile에서는 의존 관계를 직접 지정한다.
의존 관계(2) • gcc -M $(SRCS) > .depend • include .depend • 헤더파일 의존성 관계 생성 • GNU 컴파일러(gcc)에서 제공하고 있는 -M 옵션을 이용하게 되면, 의존파일의 리스트를 만들어 낼 수 있게 된다. • 의존관계를 만들고 include문을 통하여 .depend파일을 Makefile에 인클루드 시킨다. • gcc를 사용할 경우, gccmakedep 명령을 이용하면 의존관계를 쉽게 만들어 낼 수 있다.
프로젝트 관리(1) • make –C <DIR> • 재귀적 사용 • 대부분의 프로젝트에서는 소스 파일을 계층 구조의 디렉토리로 만들어서 make에서 사용할 수 있도록 한다. • 각 하위 디렉토리에 별도의 기술 파일을 두고 마스터 기술 파일에서 이들 make를 재귀적으로 실행하여 연결 한다.
프로젝트 관리(2) • [Makeflie의 내용] • CFLAGS = -DTEST • [Source Code의 내용] • #ifdef TEST • test_print(); • #endif • make –f ./test.mk • 컴파일러 옵션과 #ifdef 지시자 • #ifdef나 #ifndef와 같은 전처리 지시자를 사용하는 조건부 컴파일은 소프트웨어 발전과 함께 불가피한 선택이 되고 있다. • 기술 파일 이름 • -f 옵션을 사용하여 기본 이름과 다른 이름의 기술 파일을 지정 할 수 있다.
Makefile 예제(1) io.h main.c foo.c bar.c main.o foo.o bar.o test 예제의 구조
Makefile 예제(2) all: test test : main.o foo.o bar.o gcc –o test main.o foo.o bar.o main.o : io.h main.c gcc –c main.c foo.o : io.h foo.c gcc –c foo.c bar.o : io.h bar.c gcc –c bar.c ♣ 아무런 기능을 사용하지 않았을 경우
Makefile 예제(3) OBJS = main.o foo.o bar.o SRCS = main.c foo.c bar.c CC = gcc CFLAGS = -g -c TARGET = test all: $(TARGET) $(TARGET) : $(OBJS) $(CC) -o $(TARGET) $(OBJS) clean : rm -rf $(OBJS) $(TARGET) core main.o : io.h main.c foo.o : io.h foo.c bar.o : io.h bar.c ♣ 매크로를 사용하였을 경우
Makefile 예제(4) CC = gcc CFLAGS = -O2 -g OBJS = main.o foo.o bar.o SRCS = $(OBJS:.o=.c) TARGET = test all: $(TARGET) $(TARGET) : $(OBJS) $(CC) -o $@ $(OBJS) dep: gccmakedep $(SRCS) clean : rm -rf $(OBJS) $(TARGET) core ♣ 매크로와 확장자 규칙을 사용했을 경우
Makefile 작성 가이드 라인(1) 살펴본 3개의 Makefile은 모두 같은 일을 하는 Makefile의 예제이다. 맨 마지막의 Makefile의 예제가 간결하고 보기 쉬운 Makefile임을 알 수 있다.
Makefile 작성 가이드 라인(2) • 매크로 정의 부분 • 타켓을 얻기 위한 명령어 부분 • 의존 관계 부분 • 최대한 매크로를 많이 사용한다. • Makefile이 깔끔해질 뿐 아니라, 내용의 수정도 용이해 진다. • 확장자 규칙은 무조건 이용 • 일반적인 Makefile 구성방법