Make를 사용하는 이유

하나의 파일에 모든 소스코드를 담아서 작성할 경우 작은 파일은 관리가 쉽지만 라인수가 길어질수록 관리가 어려워짐

- 많은 라인, 많은 모듈과 컴포넌트, 여러명이 동시에 작업할 경우

 

문제점

1. 어떤 기능, component들이 있는지 파악이 어려움->원하는 소스코드를 찾기 어려움

 

2. 컴파일을 할 경우 전체적으로 다시 실행시켜야하기 때문에 오래걸림

 

3. 작은 수정에도 전체적인 수정으로 바뀌기 때문에 모든 기능을 다시 컴파일 해야됨

 

4. 다른 프로그래머들이 한 파일을 동시에 변경하기가 어려움

 

해결방안

1. 여러개의 파일로 나누어 관리 - 여러 모듈과 파일로 관리

 

2. header는 함수의 prototype이 들어 있음, .c파일은 모듈의 함수 정의가 들어있음

 

3. 무언가를 수정할 때, minimum compilation(최소)이 가능해짐

 

ex) mozilla는 2500개의 subdirectory들과 26000여개의 파일들이 서로 복잡한 구조로 얽혀있음

 

 

여기서 생기는 또 다른 문제 : 컴파일 명령어 입력, 어떤 파일이 변경되었는지 확인, 파일들간의 의존성을 체계적으로 관리 -> make utility을 사용함으로써 해결

 

make file : 스크립트 파일로써 어떻게 컴파일 할 것인지 정해놓음 - Rules, Command

make file을 읽어서 target을 만듦 -> target을 만드는데 다른 파일들이 필요한 경우 -> 존재한다면 가져다 사용하고 존재하지 않는다면 의존하는 파일들을 만들어감

 

즉, 상위 Target으로부터 하위로 내려가며 의존파일들을 확인해 나감(chain)

 

target이 의존파일보다 오래되었는지 확인(시간체크)하고 다시 compile할지 정함

 

ex) main.c sum.c sum.h의 의존 관계도 -> sum이라는 파일을 만들 때

화살표로 연결되어있는 것들이 서로 의존성을 가짐

 

depend on

ex) Rules

sum(타겟) : main.o sum.o(의존 파일)

[TAB](꼭 써줘야됨) gcc -o sum main.o sum.o(명령어 shell lines)

가장 마지막에 생성되는 타겟으로부터 아래로 내려오며 의존파일들을 써내려감

 

component

# : comment

 

\ : 다음 라인과 연결

 

Rules : 언제 어떻게 만들것인지 정한 규칙

 

※ make -p : 사용자가 정의하지 않고도 묵시적으로 정의된 rule들을 출력

   main.o test.o : ~.h -> 한번에 두가지 타겟을 쓸 수도 있음

 

Shell Lines (명령어) : 여러가지 명령어를 쓸 수도 있음, TAB이 꼭 필요

ex) ... : ...

commend 1

commend 2

.

.

 

Macros(매크로) : 동일한 타이핑을 줄이기 위해 사용, make파일이 한꺼번에 변경됨

선언 : MACRONAME = macro value

사용 : ${MACRONAME}  or $(MACRONAME)

 

ex) HOME = /home/courses/ese101 <- 이 경로를 HOME으로 지정

     CPP = $(HOME)/cpp <- 여기부터 아래로 쓰이는 HOME은 모두 위 경로

     TCPP = $(HOME)/tcpp

     PROJ = .

     INCL = -I $(PROJ) –I$(CPP) –I$(TCPP)

     선언한 라인에서 경로를 수정하여도 아래 라인들은 HOME으로 호출하기 때문에 수정      안해도 됨

 

Examples of macros

lib.o(10:10): aaa.c(10:12) bbb.c(9:30)

 

Macro

Meaning 

example 

$@ 

Full target name(타겟 이름)

echo “target $@”  -> lib.o

$?

언제 생성되었는지 확인하여 타겟보다 늦게 만들어진 파일을 찾음 

echo “newer sources $?”  -> aaa.c

$<

첫번째 의존 파일

echo “first source $<“ -> aaa.c

$^

모든 의존 파일

 

$*

확장자를 뺀 Target

echo “target without suffix $*” -> lib

 

Makefile 예제

 % gcc -o binary lib.o prog.o

 

binary: lib.o prog.o

gcc -o binary lib.o prog.o

 

binary: lib.o prog.o

gcc -g -Wall -o binary lib.o prog.o


lib.o: lib.c

gcc –o lib.o -g -Wall -c lib.c

 

prog.o: prog.c

gcc –o prog.o -g -Wall -c prog.c

 

clean:

rm *.o binary

 

겹치는 옵션들 매크로로 대체가능

 

CC = gcc

CFLAGS = -g -Wall

OUTPUT = binary


$(OUTPUT): lib.o prog.o

$(CC) –o binary $(CFLAGS) lib.o prog.o


lib.o: lib.c

$(CC) –o lib.o $(CFLAGS) -c lib.c


prog.o: prog.c

$(CC) –o prog.o $(CFLAGS) -c prog.c

 

clean:

rm *.o $(OUTPUT)

 

겹치는 object파일도 매크로로 설정 가능

 

CC = gcc

CFLAGS = -g -Wall

OUTPUT = binary

OBJFILES = lib.o prog.o


$(OUTPUT): $(OBJFILES)

$(CC) $(CFLAGS) $(OBJFILES) -o binary


lib.o: lib.c

$(CC) $(CFLAGS) -c lib.c -o lib.o


prog.o: prog.c

$(CC) $(CFLAGS) -c prog.c -o prog.o


clean:

rm *.o $(OUTPUT)

 

단순히 .c -> .o파일로 바뀐다는 약속일 경우 %를 써주면 모든 .c파일은 .o파일로 만들어 낸다는 commend 가능

 

CC = gcc

CFLAGS = -g -Wall

OUTPUT = binary

OBJFILES = lib.o prog.o


$(OUTPUT): $(OBJFILES)

$(CC) $(CFLAGS) $(OBJFILES) -o binary


%.o: %.c

$(CC) $(CFLAGS) -c $< -o $@


clean:

rm *.o $(OUTPUT)

 

.SUFFIXES: .o .c 라는 매크로로 Rule을 지정 할 수 있음

 

최종

 

CC = gcc

CFLAGS = -g -Wall

OUTPUT = binary

OBJFILES = lib.o prog.o

.SUFFIXES: .o .c


$(OUTPUT): $(OBJFILES)

$(CC) $(CFLAGS) $(OBJFILES) -o binary


.c.o:

$(CC) $(CFLAGS) -c $< -o $@


clean:

rm *.o $(OUTPUT)

 

.PHONY target : 타겟이 파일형태가 아닌 명령어형식으로 지정하여 사용하는 것

clean:

/bin/rm -f *.o core

 

 

 

 

커멘드 : make clean

 

Standard phony targets

target 

의미 

all 

모든 규칙을 적용(make 순서를 지정)

install 

결과를 디렉토리에 설치

clean 

컴파일과정중에 생성된 .o파일 삭제 

distclean 

컴파일과정중에 생성된 모든 파일 삭제 

 

Recursive make : make파일은 하나가 아니라 모든 디렉토리에 존재하여 상위 make파일이 하위 make파일을 호출하여 실행하는 것 -> 복잡해짐

 

상위 makefile은 하위 makefile을 호출한 후 컴파일하여 매우 유용

하위 makefile은 자신이 해당되는 디렉토리를 어찌 컴파일할지 정해져있음

 

ex)

DIRS = lib app

.PHONY: all clean


all:

@for d in $(DIRS); \ -> @는 결과를 프린트 하지 말라는 의미, 모든 Directory(lib,app)의

do \

$(MAKE) –C $$d; \  -> make파일을 호출 후 해석하지 않고 그대로 넘김

done


clean:

@for d in $(DIRS); \ -> 모든 디렉토리에서

do \

$(MAKE) –C $$d clean; \ ->make파일안의 clean명령어 수행

done

 


 

 

'임베디드SW공학' 카테고리의 다른 글

[6주차]Linux/Unix System Programming  (0) 2018.11.01
[5주차]git  (0) 2018.10.16
[3주차]GCC&library  (0) 2018.10.07
[2주차]Shell Script Programming  (0) 2018.09.26
[1주차]Linux Terminology  (0) 2018.09.26

+ Recent posts