Linux 커널

makefile분석

룸훼훼 2010. 9. 28. 09:21
반응형
 
#-----------------------------
# 2008 Mecha Cource - By CM WC, 2008.09.10. // 주석처리.. makefile에 대한 설명
#-----------------------------
ifndef ERASE_FCT   // ERASE_FCT가 정의되어있지 않다면 5번 줄을 실행해라라는 뜻.
ERASE_FCT=rm -rf // -r은 지울 때 물어보지 않게 -f는 지울수 있는건 다지워라라는 뜻.
endif // ifndef ERASE_FCT의 끝
ifndef WCCROSS_COMPILE // WCCROSS_COMPILE이 정의 되어있지 않다면 8번 줄을 실행해라
WCCROSS_COMPILE=arm-elf-
endif // WCCROSS_COMPILE의 끝

WCTOOL=gcc // gcc를 선언한다. (스크립트 언어로 WCTOOL라는 변수에 gcc를 저장)

WCOUTFILE_SRAM=at91sam7s_sram_wc // 생성될 elf파일의 이름을 스크립트 언어로 선언
WCOUTFILE_FLASH=at91sam7s_flash_wc // 생성될 elf파일의 이름을 스크립트 언어로 선언

WCTARGET=AT91SAM7S256 //타켓이름을 선언

WCINCL=./include //현재 위치의 include 파일 선언(gcc 옵션 중에서 -I옵션으로 제일 처음 참조할 위치의 include)

# Debug Mode //코드에 대한설명 MAKEFILE에서는 주석처리를 #으로 한다.
OPTIM=-Os // gcc 옵션 중 최적화 옵션으로 -Os는 크기를 최적화하는 옵션이다.
//********** gcc 최적화 옵션에 대한 부가설명 ***********
             //-O -O1과 같음
             //-O0 최적화를 하지 않음
             //-O1 코드사이즈의 감소와 실행속도향상을 목표로 최적화함
             //변수를 레지스터에 할당하거나,다중조건점프의 최적화등을 행함
             //-O2 고도의 최적화를 하며, 대부분이 최적화가 됨.
             //루프전개와 함수의 인라인전개,레지스터의 rename을 하지않음.
             //-O3 -O2 것보다 진보된 최적화를 행함.
             //루프전개나 함수의 인라인 전개등도 행함.
             //-Os 코드사이즈를 작게 하기 위한 최적화를 행함.
             //-O0∼3등의 실행 속도를 향상시키는 옵션을 모두 병행할 수 있음.

ifeq ($(WCTOOL), gcc) // ifeq에서 eq는 equal로서 C에서 조건문과 같은 역할을 한다.
                        // 만역 WCTOOL(위에서 gcc라고 선언하였다.) 과 gcc가 같다면 이라는 뜻으로
                        // 성립한다면 endif를 만나기까지의 코드를 실행하게 된다.(23번라인부터 43번라인의 endif까지)

AS=$(WCCROSS_COMPILE)gcc //AS는 Assembler
CC=$(WCCROSS_COMPILE)gcc //CC는 C complier
LD=$(WCCROSS_COMPILE)gcc //LD는 linker
                               // AS, CC, LD는 미리 정해져 이쓴 매크로이다. make -p라고 입력해보면 make에서
                               // 미리 세팅되어 있던 모든 값들이 엄청난 스크롤과 함께 나타난다.
                               // 여기서는 AS CC LD를 우리한테 맞게끔 arm-elf-gcc로 재정의 해주었다.

OBJCOPY=$(WCCROSS_COMPILE)objcopy
//objcopy는 컴파일시에 TEXT영역, BSS영역,CODE영역의 필요한 부분들을 잘라서 복사하는 명령어다.
// 파일의 사이즈를 줄이는데 사용할 수 있고, 바이너리 포맷을 바꾸는 데도 사용할 수 있다.
OBJDUMP=$(WCCROSS_COMPILE)objdump
//objdump는 디버깅 정보를 출력하는데 사용하는 명령어다. (역어셈블)

NM= $(WCCROSS_COMPILE)nm // nm은 덤프된 파일의 정보를 보여주는 명령어다.
SIZE=$(WCCROSS_COMPILE)size // size 명령어는 해당 섹션 영역의 사이즈를 볼수 있다.
//****************************************************************************************************
// ifndef부터 여기까지 명령어는 ARM Tool을 사용하겠다고 우리가 재정의 한 것으로
// 해당 명령어는 C:\Program Files\GNUARM\bin폴더에서 확인할 수 있다.
//****************************************************************************************************

CCFLAGS=-g -mcpu=arm7tdmi $(OPTIM) -Wall -I$(WCINCL) -D$(WCTARGET)
// C complier의 플래그로 컴파일할 때 주는 옵션을 정의해 놓은것이다.
// -g는 바이너리 파일에 디버깅 정보를 삽입하는 옵션
//mcpu는 사용할 코어가 arm7tdmi를 뜻하고 OPTIM은 위에서 정의한 최적화 옵션
//-Wall은 경고(Warning)를 전부 출력하라는 옵션
//-I는 뒤에 WCINCL의 경로를 우선 참조하라는 옵션
//-D는 define의 약자로 뒤따라오는 내용을 define한다는 옵션
// (define의 종류에는 소스코드에서 #define 하는 방법과 컴파일할 때 -D옵션으로 define하는 방법 2가지다.)
// -c는 오브젝트 파일을 생성하라는 옵션
ASFLAGS=-D__ASSEMBLY__ -D$(WCTARGET) -g -mcpu=arm7tdmi -c $(OPTIM) -Wall -I$(WCINCL)
LDFLAGS+=-nostartfiles -Wl,--cref
LDFLAGS+=-lc -lgcc
LDFLAGS+=-T elf32-littlearm.lds

OBJS=cstartup.o // 오브젝트 파일 이름
endif
//*******************************************************************************************************
// 1번 라인부터 여기까지는 거의 스크립트 언어로 변수를 선언하는 부분이다.
// 스크립트 언어로 변수를 선언할 때 주의해야 할 점은 C언어처럼 절차지향적이기 때문에 먼저 선언되어야
// 밑에서 사용할 수 있다.
//*******************************************************************************************************

OBJS+= lowlevel.o \
       main.o

all: sram flash
    @echo "make start!!"

rebuild: clean all
    @echo "make rebuild start!!"

sram: $(OBJS)
    $(LD) $(LDFLAGS) -Ttext 0x201000 -Tdata 0x200000 -n -o $(WCOUTFILE_SRAM).elf $(OBJS)
    $(OBJCOPY) --strip-debug --strip-unneeded $(WCOUTFILE_SRAM).elf -O binary $(WCOUTFILE_SRAM).bin

flash: $(OBJS)
    $(LD) $(LDFLAGS) -Ttext 0x100000 -Tdata 0x200000 -n -o $(WCOUTFILE_FLASH).elf $(OBJS)
    $(OBJCOPY) --strip-debug --strip-unneeded $(WCOUTFILE_FLASH).elf -O binary $(WCOUTFILE_FLASH).bin

main.o: main.c
    $(CC) -c $(CCFLAGS) main.c -o main.o

lowlevel.o: lowlevel.c
    $(CC) -c $(CCFLAGS) lowlevel.c -o lowlevel.o

cstartup.o:  cstartup.S
    $(AS) $(ASFLAGS) cstartup.S -o cstartup.o

clean:

    $(ERASE_FCT) *.o *.bin *.elf *.map
    @echo " -----------------------"


Makefile의 실행 순서

target ... : dependency ...

command

makefile은 목표(target), 의존 관계(dependency), 명령(command)의 세개로 이루어진 기분적인 규칙(rule)들이 계속적으로 나열되어 있다.

먼저 "make"명령을 실행하게 되면 Makefile을 순차적으로 읽어서 가장 처음에 나오는 규칙을 수행하게 된다.

여기서 all이라는 Dummy Target이 바로 첫번째 타겟이된다.

all: sram flash

@echo "make start!!"

all을 만나면 의존성 검사를 하게 되는데 먼저 sram을 참조하고 flash를 참조하게 된다.

sram: $(OBJS)

$(LD) $(LDFLAGS) -Ttext 0x201000 -Tdata 0x200000 -n -o $(WCOUTFILE_SRAM).elf $(OBJS)
$(OBJCOPY) --strip-debug --strip-unneeded $(WCOUTFILE_SRAM).elf -O binary $(WCOUTFILE_SRAM).bin

sram에서 다시 의존성 검사를 하게되는데 $(OBJS)를 검사하게 된다. $(OBJS)는 위에서 cstartup.o라고 정의되어 있고

그 밑에 lowlevel.o와 main.o가 덧붙여 정의되어 있다.

이 OBJS를 참조하여 다시 cstartup.o를 찾는다.


cstartup.o: cstartup.S
$(AS) $(ASFLAGS) cstartup.S -o cstartup.o

여기서 또 다시 의존성 검사를 한다. 이번에는 cstartup.S 를 참조하여 컴파일을 하게 된고 cstartup.o가 생성된다.

그리고 lowlevel.o를 찾아서 lowlevel.c를 참조하여 lowlevel.o를 생성한다.

마찬가지로 main.o를 찾아서 main.c를 참조하여 main.o를 생성한다.


여기까지가 startup.o, lowlevel.o, main.o 가 생성된 화면이다.

그리고 제어권이 의존성 검사를 한 sram으로 넘어가고 sram의 command를 실행하게 된다.

sram까지 실행한 화면이다.

다음은 sram에서 flash로 넘어와서 flash의 command를 실행하게 된다.

마지막으로 final의 command를 실행한 장면이다. 맨 마지막 줄의 "make start!!" 라는 all의 command를 마지막으로 실행

하게 된다.

이렇게 makefile의 기본적인 규칙으로 의존성을 검사하면서 하나하나 makefile을 분석해 나가면 아무리 긴 makefile이라

도 분석이 가능하다.


반응형

'Linux 커널' 카테고리의 다른 글

tar 명령어  (0) 2011.02.11
====가상주소====  (0) 2010.09.28
source insight 프로젝트 생성하기  (0) 2010.09.28
u-boot  (0) 2010.09.28
리눅스 명령어  (0) 2010.09.07