펌웨어 기본기를 닦는 과정입니다.
a. Makefile은 일종의 매크로이다. 컴파일러로 .out/ .exe/ .axf와 같은 실행파일을 만들 때 여러 번 쓰지 않고 Makefile 하나만 실행해서 만들 수 있기 때문에 유용하다.
b. 우선 c언어를 gcc를 이용하여 오브젝트 파일로 만든다. 여기에서는 main.c와 motor.c를 사용한다.
gcc -c main.c motor.c
(-c 옵션은 .c를 사용하여 .o를 만들어준다. )
그러면 main.o, motor.o가 생성이 된다.
c. 만들어진 main.o를 링커에 넣어 바이너리로 이루어진 실행파일로 만든다.
gcc -o app.out main.o motor.o
(-o옵션은 오브젝트 파일을 사용하여 .out 파일을 만든다. app.out은 임의의 이름으로 된 실행파일이다.)
d. 이렇게 기본적인 컴파일 과정이 있는데 실제로 리눅스에서 gcc를 이용하여 이렇게 실행파일로 만들 수 있다. 하지만 이 과정을 한 번에 처리해 줄 수 있는 것이 Makefile이다. Makefile의 기본적인 문법은 이렇다.
Target : Dependency
command
타겟은 내가 만들고 싶은 것.
디펜던시(종속성)는 타깃을 만들 때 필요한 것.
커맨드는 타깃을 만드는 데 필요한 코드.
e. 위의 과정을 Makefile에 적으면 아래와 같다.
app.out : main.o motor.o
gcc -o app.out main.o motor.o
main.o :
gcc -c main.c
motor.o :
gcc -c motor.c
f. 이렇게 적으면 위의 과정과 똑같다고 할 수 있다. 그런데 Makefile에서 최종 결과물을 명시해주기 위해 all이라는 명령어를 쓴다. all은 내가 원하는 최종 결과물이다. all을 안 쓰면 1개의 타깃만 만들고 종료한다. 쓰는 순서는 모두 상관이 없다.
all : app.out
app.out : main.o motor.o
gcc -o app.out main.o motor.o
main.o :
gcc -c main.c
motor.o :
gcc -c motor.c
이렇게 하면 Makefile 쓰는 기본은 끝이다.
-------------------------------------------------------------------응용-----------------------------------------------------------
더 깔끔하게 쓰고 싶거나 그렇게 써진 Makefile을 해석할 때 필요한 문법들이다.
변수 선언
CC = gcc
TARGET = app.out
OBJS = main.o motor.o
변수 사용
$(TARGET) : $(OBJS)
$(CC) -o $(TARGET) $(OBJS)
main.o :
$(CC) -c main.c
motor.o :
$(CC) -c motor.c
여기서 저 $(TARGET)이나 $(OBJS)를 두 번 쓰는 게 싫다! 고 한다면
$@는 타깃이라는 뜻.
$^는 종속성이라는 뜻.
표시를 써주면 된다.
$(TARGET) : $(OBJS)
$(CC) -o $@ $^
또한 main.c motor.c도 쓰기 싫고 모든 c파일을 오브젝트로 바꾸고 싶을 때 $<기호를 써주면 된다.
.c.o :
$(CC) -c -o $@ $<
이렇게 쓰면 gcc -c main.c motor.c과 같은 뜻이다.
최종본은 아래와 같다.
CC = gcc
TARGET = app.out
OBJS = main.o motor.o
$(TARGET) : $(OBJS)
$(CC) -o $@ $^
.c.o :
$(CC) -c -o $@ $<
실제 사용되는 메이크 파일 또한 비슷한 구성으로 되어있다. 옵션과 라이브러리가 추가되어있는 make파일 일부분이다.
'공부 > 펌웨어&RTOS' 카테고리의 다른 글
2. 임베디드 펌웨어 테스트하기 (feat. QEMU, gdb) (0) | 2021.08.09 |
---|---|
0. 임베디드 운영체제 요약 (0) | 2021.06.29 |