뭘 알아야 이해를 하지
메이크 파일이 뭘까요? 꼭 필요한 걸까요? 메이크 파일이 없으면 개발이 안될까요? 아닙니다. 다만 개발할 때 불편할 뿐이죠. ᄏᄏ
(A)~(D)단계까지 가면 최종적으로 타겟 플래시 메모리에 올라간 메인 바이너리가 만들어진답니다. 여기서 각 단계별로 빌드 과정이 다른데, 한번 만에 빌드 과정을 할 수 있도록 제공해 주는 것이 메이크 파일(makefile)이라고 보시면 됩니다.

먼저 (A)단계를 살펴보죠.
startup.s와 main.c 라는 프로그램 만들었어요. 이 프로그램이 잘 동작하려면 해당 언어에 맞는 컴파일를 이용해서 컴파일을 해야겠죠. 컴파일 하기 위해서는 컴파일러가 설치 되어 있어야 한다는 것을 알고 계시죠? 컴파일로는 공짜 암지씨씨(ARM-GCC) 또는 상용 컴파일러 에이디에스(ADS)을 설치하면 됩니다. 여기서는 암지씨시를 사용해 보겠습니다.
컴파일을 해 볼께요.
▶예제
CMD> arm-elf-as ./sources/Startup.s -marm9tdmi -EL -M --gdwarf2 -o Startup.o
CMD> arm-elf-gcc ./sources/main.c -g -gdwarf-2 -O0 -c -mcpu=arm9tdmi -mlittle-endian -mapcs-frame -mno-apcs-stack-check -o main.o
이제 두 번째 B단계랍니다.
A단계에서 Startup.o와 main.o을 가지고 링크를 시켜야 해요. 이 과정을 거치고 나면 *.elf 파일이 만들어 진답니다. 링크를 시켜는 파일은 arm-elf-ld 인데 컴파일러 버전에 따라 arm-elf-gcc에서도 링크 역할을 해 주기도 한답니다.
▶예제
CMD> arm-elf-gcc -Bstatic -nostartfiles -Xlinker --script=linker.ld -lc -o general.elf Startup.o main.o
CMD> arm-elf-gcc ./sources/main.c -g -gdwarf-2 -O0 -c -mcpu=arm9tdmi -mlittle-endian -mapcs-frame -mno-apcs-stack-check -o main.o
세 번째 단계는 B단계에서 만들어진 general.elf 파일을 가지고 바이너리를 만든답니다.
▶예제
CMD> arm-elf-objcopy general.elf --output-target=binary general.bin
CMD> arm-elf-gcc ./sources/main.c -g -gdwarf-2 -O0 -c -mcpu=arm9tdmi -mlittle-endian -mapcs-frame -mno-apcs-stack-check -o main.o
최종적으로 binary가 만들어 졌는데 중간중간에 프로그램 소스가 수정이 된다면 위의 단계를 처음부터 다시 해야겠죠? 하지만 이렇게 반복적인 일을 번번히 커맨드 입력해서 컴파일을 한다면 어느 누가 개발을 하겠습니까? 얼마나 귀찮을까요? 그리고 한동안 컴파일이라는 것을 안 하다가 다시 할 일이 생긴다면 컴파일 명령어가 기억 나지 않을 때가 종종 있을 때, 그때마다 다시 문서 찾아 컴파일 옵션 보는 것도 피곤한 일이죠. 그래서 조금이라도 더 컴파일을 편리하게 하기 위해서 메이크 파일을 만들며 관리를 한답니다. 마치 도스에서 배치파일처럼 사용하죠.
메이크 파일은 스크립트로 되어 있으며 어떤 소스 파일들을 컴파일 할지, 컴파일 옵션은 어떻게 하는지 등을 정의해 놓고 개발자는 컴파일 할 때 메이크 파일 하나만 실행하면 컴파일이 되도록 만든답니다. 사용하는 컴파일러에 따라 메이크 파일 내용도 다르답니다. 메이크 파일이름은 Makefile이고, 컴파일을 할 때는 Make라고 입력하시면 됩니다. 이 메이크 파일이 실행되기 위해서는 컴파일러를 설치했을 때 Make라는 유틸리티가 있는지 확인을 해 보시고, 만약 없다면 Make라는 유틸리티를 설치하시면 된답니다.

▶코드 Makefile
##### File Definition ####
PRJ = general
INIT1 = Startup
CM1 = main
#### Destination path Definition ####
PRE=arm-elf
SOURCES=./sources/
#### ARM tool Definition ####
ARMASM = $(PRE)-as
ARMCC = $(PRE)-gcc
ARMLINK = $(PRE)-gcc
ARMSIZE = $(PRE)-size
ARMOBJCOPY = $(PRE)-objcopy
#### Option Definition ####
AFLAGS = -marm9tdmi -EL -M --gdwarf2
CFLAGS = -B$(GCC_EXEC_PREFIX) -g -gdwarf-2 -O0 -c -mcpu=arm9tdmi -mlittle-endian -mapcs-frame -mno-apcs-stack-check
LFLAGS = -Bstatic -nostartfiles -Xlinker --script=linker.ld -lc
OBJS = $(INIT1).o $(CM1).o
$(PRJ).elf: $(OBJS)
$(ARMLINK) $(LFLAGS) -o $(PRJ).elf $(OBJS)
$(ARMOBJCOPY) $(PRJ).elf --output-target=binary $(PRJ).bin
$(ARMSIZE) $(PRJ).elf
all: clean $(PRJ).elf
clean:
rm -f *.o
rm -f $(PRJ).src
rm -f $(PRJ).elf
$(INIT1).o: $(SOURCES)$(INIT1).s
$(ARMASM) $(SOURCES)$(INIT1).s $(AFLAGS) -o $(INIT1).o
$(CM1).o: $(SOURCES)$(CM1).c
$(ARMCC) $(CFLAGS) $(SOURCES)$(CM1).c -o $(CM1).o
makefile을 실행할 때는 make라고만 하시면 된답니다.
▶결과 Makefile
CMD> make
rm -f *.o
rm -f general.src
rm -f general.elf
arm-elf-gcc -Bstatic -nostartfiles -Xlinker --script=linker.ld -lc -o general.elf Startup.o main.o
arm-elf-objcopy general.elf --output-target=binary general.bin
arm-elf-size general.elf
text data bss dec hex filename
804 52 0 856 358 general.elf
이 모든 과정이 끝나고 나면 생성된 파일들을 살펴보죠.
Startup.o 스타트업 파일의 오브젝트
main.o 씨언어 메인의 오브젝트
general.elf 헤더, 바이너리, 심볼정보가 들어 있는 파일
general.bin 타겟 플래시 메모리에서 실행될 파일


댓글