본문 바로가기
Linux BSP

Makefile은 왜 사용하며, 어떻게 사용하는가

by TYB 2024. 2. 22.
반응형

linux에서 c를 컴파일하려면 gcc를 많이들 쓸것이다.

gcc iot_server.c -o iot_server -lpthread

gcc iot_client.c -o iot_client -lpthread

 

이런식으로 코드 수정하고 실행시켜볼려고 컴파일 할 때마다 라이브러리를 추가해주고 하는게 귀찮음.

그래서 컴파일 자동화해주는 Makefile을 사용하는거임.

  1 #CC:=arm-linux-gcc
  2 CC:=gcc
  3
  4 TARGET_SRV=iot_server
  5 OBJECT_SRV=$(TARGET_SRV).o
  6
  7 TARGET_CLN=iot_client
  8 OBJECT_CLN=$(TARGET_CLN).o
  9
 10 #LDFLAGS=-D_REENTRANT -pthread -lmysqlclient
 11 LDFLAGS=-D_REENTRANT -pthread
 12
 13 all : $(TARGET_SRV) $(TARGET_CLN)
 14
 15 $(TARGET_SRV):$(OBJECT_SRV)
 16     $(CC) -o $@ $(OBJECT_SRV) $(LDFLAGS)
 17 $(TARGET_CLN):$(OBJECT_CLN)
 18     $(CC) -o $@ $(OBJECT_CLN) $(LDFLAGS)
 19 %.o:%.c
 20     $(CC) -c -o $@ $<
 21 clean:
 22     rm -f *.o $(TARGET_SRV) $(TARGET_CLN)

1번 라인은 arm의 target 보드용으로 컴파일할거면 사용

2번 라인은 현재 기기에서 사용할 목적으로 컴파일

4,7 라인은 컴파일 해야할 파일이 2개이므로 2개 작성

 

11번 라인은 컴파일에 필요한 라이브러리

LDFLAGS=-D_REENTRANT -pthread

-D_REENTRANT는 쓰레드의 안전한 함수와 안전하지 않은 함수가 있는데 그 중 안전한 함수만 사용하겠다는 거임.

 

13번 라인의 하단에 아무 명령어도 없으므로, 저 조건에 맞아서 들어가도 아무 것도 없는거임.

all : iot_server iot_client

 

 

15번 라인 iot_server: iot_server.o  17번 라인 iot_client: iot_client.o

object 파일이 있을 때 만약 더 최근에 수정되었다면 실행을 안하고, 소스코드가 더 최근에 수정되었다면 16번 혹은 18번 라인의 내용을 수행하는거임.

16,18번의 내용은 맨 위의 gcc 명령어의 형태 그대로임.  gcc iot_server.c -o iot_server -D_REENTRANT -lpthread

 

19번 라인은 gcc -c -o iot_server.o iot_server.c가 되는거임. gcc -c 옵션은 object파일까지만 컴파일 하라는 뜻임.

 

만약 gcc명령어를 사용해서 컴파일을 하게 되면 object파일의 생성시간이 더 최근임.

ubuntu08@ubuntu08-VirtualBox:~/ipc/iot_socket$ ls -lt
total 80
-rwxrwxr-x 1 ubuntu08 ubuntu08 22584  2월 22 11:31 iot_server
-rwxrwxr-x 1 ubuntu08 ubuntu08 18000  2월 22 11:30 iot_client
-rw-rw-r-- 1 ubuntu08 ubuntu08  5968  2월 20 09:51 iot_client.o
-rw-rw-r-- 1 ubuntu08 ubuntu08 11328  2월 20 09:51 iot_server.o
-rw-r--r-- 1 ubuntu08 ubuntu08  7366  2월 20 09:51 iot_server.c
-rw-r--r-- 1 ubuntu08 ubuntu08   446  2월 20 09:51 Makefile
-rw-r--r-- 1 ubuntu08 ubuntu08  3038  2월 20 09:51 iot_client.c

ls -lt 명령을 쳐주면 최근 실행된 내용이 위로 정렬되면서 출력됨. 

 

이 상태에서는 make 명령어를 쳐도 코드와 object 파일의 생성시간 비교 후 make를 안함.

 

make를 다시하고 싶다면 make clean을 하던, source file을 touch해서 최종 수정시간을 object파일보다 일찍 

ubuntu08@ubuntu08-VirtualBox:~/ipc/iot_socket$ make
make: Nothing to be done for 'all'.


ubuntu08@ubuntu08-VirtualBox:~/ipc/iot_socket$ touch iot_server.c iot_client.c


ubuntu08@ubuntu08-VirtualBox:~/ipc/iot_socket$ make
gcc -c -o iot_server.o iot_server.c
gcc -o iot_server iot_server.o  -D_REENTRANT -pthread
gcc -c -o iot_client.o iot_client.c
gcc -o iot_client iot_client.o  -D_REENTRANT -pthread



ubuntu08@ubuntu08-VirtualBox:~/ipc/iot_socket$ ls -lt
total 80
-rwxrwxr-x 1 ubuntu08 ubuntu08 18000  2월 22 11:35 iot_client
-rw-rw-r-- 1 ubuntu08 ubuntu08  5968  2월 22 11:35 iot_client.o
-rwxrwxr-x 1 ubuntu08 ubuntu08 22584  2월 22 11:35 iot_server
-rw-rw-r-- 1 ubuntu08 ubuntu08 11328  2월 22 11:35 iot_server.o
-rw-r--r-- 1 ubuntu08 ubuntu08  3038  2월 22 11:35 iot_client.c
-rw-r--r-- 1 ubuntu08 ubuntu08  7366  2월 22 11:35 iot_server.c
-rw-r--r-- 1 ubuntu08 ubuntu08   446  2월 20 09:51 Makefile

 

 

 

 


타겟보드가 (Arm processor)를 사용하는 라즈베리파이일 때 다른 프로세서를 사용하는 ubuntu 환경에서 컴파일해서 넘겨줄 때 사용하는 Makefile의 형태

 

  1 MOD := ledkey
  2 obj-m := $(MOD).o
  3
  4 CROSS = ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
  5 #KDIR := /lib/modules/$(shell uname -r)/build
  6 KDIR := /home/ubuntu/pi_bsp/kernel/linux
  7 PWD := $(shell pwd)
  8
  9 default:
 10     $(MAKE) -C $(KDIR) M=$(PWD) modules $(CROSS)
 11     cp $(MOD).ko /srv/nfs
 12 clean:
 13     rm -rf *.ko
 14     rm -rf *.mod.*
 15     rm -rf .*.cmd
 16     rm -rf *.o
 17     rm -rf modules.order
 18     rm -rf Module.symvers
 19     rm -rf $(MOD).mod
 20     rm -rf .tmp_versions
~

1번 라인은 Make할 파일 이름

4번 라인은 Make할 타겟 cpu 

6번 커널 디렉터리 경로

7번 현재 경로

 

9,12번 라벨명(default, clean)

 

make default = make 명령어를 칠 때 default의 내용(9~11번 라인)을 수행하는거고

make clean 명령어를 칠 때 clean의 내용(13~20라인)을 수행하는거임.

 

space로 들여쓰기를 하면 make가 안됨. 들여쓰기는 반드시 tab으로 들여쓰기를 해줘야함.

뒷 공간에 space하나라도 들어가 있으면 눈에는 안보이는데 make가 안됨.

 

$(MAKE) -C $(KDIR) M=$(PWD) modules $(CROSS)

-C 명령어를 줬다는 것은 다른 디렉터리의 Makefile을 기반으로 돌린다는 거고, 그 중 modules만 컴파일 하도록 M 명령어를 넣어준거임.

그래서 현재 디렉터리의 있는 ledkey라는 파일만 arm processor 기반으로 컴파일해라.

 


 

반응형