1. 程式人生 > >LCD實驗學習筆記(一):Makefile

LCD實驗學習筆記(一):Makefile

主Makefile總領全域性的就這句——

lcd.bin: $(objs)

要生成lcd.bin,依賴於objs列舉的一堆檔案:head.o init.o nand.o interrupt.o serial.o lcddrv.o framebuffer.o lcdlib.o main.o lib/libc.a

所以要先找到這些檔案,幾個.o,還有一個.a

.o目標檔案怎麼生成?

%.o:%.c和%.o:%.S是生成規則,就是依賴於.c或.S檔案,使用交叉編譯命令生成。

.a是庫檔案,到lib子目錄裡去找,在子目錄裡用make命令生成

下面逐行解讀:


CC = arm-linux-gcc

   //編譯器。定義CC變數,為了簡化書寫

LD = arm-linux-ld  //聯結器。定義LD變數,為了簡化書寫
AR = arm-linux-ar  //庫管理器。將多個可重定位的目標模組歸檔為一個函式庫檔案。這個變數在lib/makefile檔案中使用了
OBJCOPY = arm-linux-objcopy
OBJDUMP = arm-linux-objdump

INCLUDEDIR := $(shell pwd)/include   //定義標頭檔案目錄變數  $(shell pwd)為獲取當前工作路徑
CFLAGS := -Wall -O2  //GCC的編譯引數  -Wall顯示所有編譯錯誤或警告  -O2優化選項,編譯時使用2級優化
CPPFLAGS := -nostdinc -I$(INCLUDEDIR)

   //GCC編譯引數  -nostdinc忽略預設目錄  -Idir把dir加到標頭檔案的搜尋路徑中,而且gcc會在搜尋標準標頭檔案之前先搜尋dir.  


備註:‘=’與‘:=’的區別:

   “=”:make會將整個makefile展開後,再決定變數的值。也就是說,變數的值將會是整個makefile中最後被指定的值。看例子:

            x = foo
            y = $(x) bar
            x = xyz

      在上例中,y的值將會是 xyz bar ,而不是 foo bar 。

      “:=”表示變數的值決定於它在makefile中的位置,而不是整個makefile展開後的最終值。

            x := foo
            y := $(x) bar
            x := xyz

      在上例中,y的值將會是 foo bar ,而不是 xyz bar 了。


 

export CC LD AR OBJCOPY OBJDUMP INCLUDEDIR CFLAGS CPPFLAGS  //這些變數將傳遞到下級Makefile,本檔案中指的是生成lib/libc.a庫檔案時的Makefile

objs := head.o init.o nand.o interrupt.o serial.o lcddrv.o framebuffer.o lcdlib.o main.o lib/libc.a    //定義變數objs,包含了生成目標檔案所需的檔案

lcd.bin: $(objs)  //定義生成目標lcd.bin,依賴於objs物件。執行這條命令時,先生成所有依賴檔案,然後依次執行下面三條命令
  ${LD} -Tlcd.lds -o lcd_elf $^  //執行shell命令,LD變數前面定義”LD = arm-linux-ld“,即進行連線,使用lcd.lds為連線指令碼,輸出目標為lcd_elf,$^表示全部依賴檔案
  ${OBJCOPY} -O binary -S lcd_elf [email protected]  //執行shell命令,將lcd_elf檔案轉換成二進位制檔案,-O表示輸出格式,-S表示不從原始檔中複製重定位資訊和符號資訊到目標檔案中
  ${OBJDUMP} -D -m arm lcd_elf > lcd.dis  //反彙編lcd_elf檔案為lcd.dis檔案

.PHONY : lib/libc.a  //.PHONY表示偽目標,不要管lib/libc.a檔案是否存在
lib/libc.a:  //當生成依賴檔案lib/libc.a檔案時,用下面的命令段,即cd lib; make; cd ..
  cd lib; make; cd ..  //進入lib目錄,然後執行make命令,最後返回到當前目錄。在lib子目錄執行make命令時將使用子目錄的Makefile,但於由前面export命令,本檔案定義的一些變數將傳遞過去
%.o:%.c  //%萬用字元。生成xxx.o檔案先要找到xxx.c檔案
  ${CC} $(CPPFLAGS) $(CFLAGS) -c -o [email protected] $<  //-c編譯不連線。[email protected]表示目標檔案   $<表示第一個依賴檔案

%.o:%.S
  ${CC} $(CPPFLAGS) $(CFLAGS) -c -o [email protected] $<

clean:  //這個clean目標沒有依賴物件,肯定是生成不了clean檔案的,但會執行下面的命令。前面寫明.PHONY : clean就更清楚了
  make clean -C lib
  rm -f lcd.bin lcd_elf lcd.dis *.o