컴퓨터공부/Embedded

Makefile 만들기

achivenKakao 2007. 5. 16. 03:13
 1. 개요

     이번 강의는 이지보드에 디바이스 드라이버를 만들기 위하여 사용되는 전형적인 Makefile의

     구성에 대하여 기술한 강의입니다.



   2. i386용 Makefile

     이 메이크 화일은 맨처음 오렐리의 소스에서 받아서 고쳐 버린 것입니다.

     실제 실전에 사용하다보니 이렇게 바뀌어 버렸습니다.

     본 강사가 사용하는 전형적인 모듈 컴파일용 Makefile의 내용을 보기로 합시다.

     [ Makefile ]

 1
 2 CC = gcc
 3 CXX = g++
 4 AR = ar
 5 LD = ld
 6 NM = nm
 7 STRIP = strip
 8 OBJCOPY = objcopy
 9
 10 CP = cp
 11 MV = mv
 12
 13 KERNELDIR = /usr/src/linux
 14 INCLUDEDIR = -I$(KERNELDIR)/include -I./
 15
 16 include $(KERNELDIR)/.config
 17
 18 CFLAGS += -Wall -D__KERNEL__ -DMODULE $(INCLUDEDIR) $(DEBFLAGS)
 19
 20 TARGET = prnport
 21
 22 OBJS = $(TARGET).o
 23
 24 SRCS = prn_main.c
 25
 26 CFLAGS += -O2
 27 #CFLAGS += -g
 28
 29 all: $(TARGET).o
 30
 31 $(TARGET).o: $(SRCS:.c=.o)
 32 $(LD) -r $^ -o $@
 33
 34 clean:
 35 rm -f *.o *~ core .depend
 36
 37 dep :
 38 gccmakedep $(INCLUDEDIR) $(SRCS)
 39

     [ Makefile ]

     오타가 끼어 들수 있으므로 여러분은 조심할것

     수행 명령은 항상 앞칸은 TAB키로 공백을 띄어야 합니다.

     이 메이크 화일은 커널 소스에 포함시켜서 사용할때는 필요없는 것이고

     모듈을 처음 작성하고 이를 시험하기 위한 경우에만 필요한 것입니다.

     임베디드 리눅스의 디바이스 드라이버를 사용하기 위해서는 꼭 필요한 것입니다.

     단 리눅스가 모듈을 지원할대의 이야기입니다.

     위에서 보여준 것이 전통적인 것은 아닙니다. 단지 본강사가 사용한 예를 보여준 것 뿐이고

     본강사 역시 오렐리의 소스를 보고 수정한 것 뿐이기 때문입니다다.


     2 CC = gcc
     3 CXX = g++
     4 AR = ar
     5 LD = ld
     6 NM = nm
     7 STRIP = strip
     8 OBJCOPY = objcopy
     9
     10 CP = cp
     11 MV = mv

     이 부분은 컴파일러 및 유틸리티 명령을 선언하는 것입니다.


     크로스 컴파일 환경일 경우 이 부분이 바뀌게 됩니다.

     이 변수명들은 make의 표준 환경 변수들이기 때문에 그대로 사용하면 make에서 알아서 처리합니다.

     13 KERNELDIR = /usr/src/linux

     모듈은 커널소스의 한부분으로 보면 되기 때문에 커널에 의존적입니다.

     그러므로 현재 사용되고 있는 커널의 디렉토리를 gcc에 알려 주어야 합니다.

     14 INCLUDEDIR = -I$(KERNELDIR)/include -I./

     모듈이 참고할 인클루드 디렉토리를 지정하는데 커널소스상에 있는 인클루드 디렉토리와

     소스가 있는 디렉토리를 포함하게 한것입니다.

     16 include $(KERNELDIR)/.config

     커널의 헤더 화일은 커널 컴파일 옵션에 영향을 받게 되어 있습니다.

     커널 컴파일 옵션은 리눅스 커널 소스가 있는 디렉토리에 .config 에 저장되어 있기 때문에

     이 부분을 포함 시켜서 컴파일시 헤더화일들이 환경 설정에 영향을 받게 하기 위해서 이 부분을

     포함 시켜야 합니다.

     18 CFLAGS += -Wall -D__KERNEL__ -DMODULE $(INCLUDEDIR) $(DEBFLAGS)

     커널소스상에 헤더 화일은 __KERNEL__ 변수가 선언되면 커널에 사용되는 헤더 화일로 동작합니다.

     모듈형식으로 디바이스 드라이버를 작성 시키기 위해서는 MODULE 이 정의 되어 있어야 합니다.

     물론 소스상에
 
      #define __KERNEL__
      #define MODULE

     이런식으로 정의 할수 있지만 소스가 여러개로 나뉠 경우 위와 같이 환경 변수로 선언하면 소스상에서

     굳이 표현하지 않아도 되기 때문에 편리하게 되지요.

     -Wall 은 컴파일시 발생하는 모든 경고 메세지를 표현하라는 의미 인데 컴파일시 발생하는 경고를 무시하게

     되면 모듈 삽입을 위하여 insmod 명량을 사용할때 심볼릭 에러를 발생하거나 모듈이 동작할때 이상하게

     동작할 수 있으므로 필히 없애는 것이 정석입니다.

     20 TARGET = prnport
     22 OBJS = $(TARGET).o

     이 문장은 최종 생성되는 화일명을 지정하게 되는데 역시 오브젝트 형입니다.

     24 SRCS = prn_main.c

     모듈의 소스들을 이 변수에 나열하면 됩니다.

     26 CFLAGS += -O2

     최적화 옵션인데 이 옵션이 없으면 커널에서 사용되는 매크로들이 확장되지 않아 제대로 컴팡일 되지 않습니다.

     27 #CFLAGS += -g

     이 문장은 컴파일한 오브젝트 모듈 화일에 디버깅 정보를 포함하라는 의미인데

     본강사도 아직 한번도 써 본적이 없습니다.

     29 all: $(TARGET).o

     make 만 단독으로 입력하여 수행하면 make 유틸리티는 Makefile에서 all부분을 찾게 되는데

     이때 만들어야 할 화일이 $(TARGET).o 가 있어야 함을 알리는 것입니다.


     31 $(TARGET).o: $(SRCS:.c=.o)
     32 $(LD) -r $^ -o $@

     이 문장이 실제 컴파일을 수행하게끔 하는 루틴 입니다.

     (SRCS:.c=.o) 는 메이크 화일의 자체 규정에 의해서 확장자가 .c 로 끝나는 화일은 .o 로 컴파일합니다.

     이때 사용하는 규칙은

     $(CC) 컴파일 명령
     $(CFLAG) 컴파일 옵션 입니다.

     이렇게 생성된 .o 화일들을 모두 모아서 한개의 .o로 만들어 주는 것이

     $(LD) -r $^ -o $@

     문장입니다.

     자세한 것은 메이크 화일 작성에 관련된 문서를 찾아 보기 바랍니다.

     어찌 되었든 모듈은 하나의 오브젝트 형태로 만들어 져야 합니다.

     34 clean:
     35 rm -f *.o *~ core .depend

     이 문장은 make clean 을 사용할때 수행되는 것입니다.

     37 dep :
     38 gccmakedep $(INCLUDEDIR) $(SRCS)

     이 문장은 make dep 을 사용할떄 수행되는 것입니다.

     헤더화일이 수정되거나 관련 화일이 수정될때 자동으로 참조 소스들이 재 컴파일 되게 하는 것입니다.




   3. ARM용 Makefile

     이것은 이지 보드에 모듈을 만들때 사용되는 메이크 화일의 예제 입니다.


     비교해 보면 i386과 거의 같을 것입니다

     [ Makefile ]

 1
 2 CC = arm-linux-gcc
 3 CXX = arm-linux-g++
 4 AR = arm-linux-ar
 5 LD = arm-linux-ld
 6 NM = arm-linux-nm
 7 STRIP = arm-linux-strip
 8 OBJCOPY = arm-linux-objcopy
 9
 10 CP = cp
 11 MV = mv
 12
 13 KERNELDIR = /myproject/kernel/linux
 14 INCLUDEDIR = -I$(KERNELDIR)/include -I./
 15
 16 include $(KERNELDIR)/.config
 17
 18 CFLAGS += -Wall -D__KERNEL__ -DMODULE $(INCLUDEDIR) $(DEBFLAGS)
 19
 20 TARGET = prnport
 21
 22 OBJS = $(TARGET).o
 23
 24 SRCS = prn_main.c
 25
 26 CFLAGS += -O2
 27 #CFLAGS += -g
 28
 29 all: $(TARGET).o
 30
 31 $(TARGET).o: $(SRCS:.c=.o)
 32 $(LD) -r $^ -o $@
 33
 34 clean:
 35 rm -f *.o *~ core .depend
 36
 37 dep :
 38 gccmakedep $(INCLUDEDIR) $(SRCS)
 39

     [ Makefile ]

     다른 부분만 열거하면 다음과 같습니다.

     2 CC = arm-linux-gcc
     3 CXX = arm-linux-g++
     4 AR = arm-linux-ar
     5 LD = arm-linux-ld
     6 NM = arm-linux-nm
     7 STRIP = arm-linux-strip
     8 OBJCOPY = arm-linux-objcopy

     당연 arm용 크로스 컴파일러와 기타 유틸리티를 지정하여야 합니다.

     13 KERNELDIR = /myproject/kernel/linux

     타켓에서 사용되고 있는 커널소스의 디렉토리를 지정하고 있습니다.

출처 : http://www.falinux.com/bbs/zboard.php?id=lec_device&page=1&sn1=&divpage=1&sn=off&ss=on&sc=on&select_arrange=headnum&desc=asc&no=6&PHPSESSID=d3f85ad4129b2b0656e9b85b74f6fbcb