天天看點

一步一步學習 Linux 驅動之驅動子產品 MakeFile 解析

make指令執行時,需要一個 Makefile 檔案,以告訴make指令需要怎麼樣的去編譯和連結程式。
           

一、使用條件判斷

    下面的例子,判斷$(CC)變量是否“gcc”,如果是的話,則使用GNU函數編譯目标。 

libs_for_gcc = -lgnu 
normal_libs = 

foo: $(objects) 
ifeq ($(CC),gcc) 
     $(CC) -o foo $(objects) $(libs_for_gcc) 
else 
     $(CC) -o foo $(objects) $(normal_libs) 
endif 
           

      可見,在上面示例的這個規則中,目标“foo”可以根據變量“$(CC)”值來選取不同的函數庫來編譯程式。 

我們可以從上面的示例中看到三個關鍵字:ifeq、else和endif。ifeq的意思表示條件語句的開始,并指定一個條件表達式,表達式包含兩個參數,以逗号分隔,表達式以圓括号括起。else表示條件表達式為假的情況。endif表示一個條件語句的結束,任何一個條件表達式都應該以endif結束。 

libs_for_gcc = -lgnu 
normal_libs = 

ifeq ($(CC),gcc) 
    libs=$(libs_for_gcc) 
else 
    libs=$(normal_libs) 
endif 

foo: $(objects) 
     $(CC) -o foo $(objects) $(libs) 
           

下面是關于一段arm驅動程式的分析

obj-m :=hello.o

KERNELDIR :=/home/ZP1015/Desktop/linux-2.6.32.2

all:
	 make -C $(KERNELDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-
clean:
	rm -f *.o *.ko *.mod.o *.mod.c *.symvers modul*
           
ifneq ($(KERNELRELEASE),)

obj-m :=hello.o

else

KERNELDIR :=/home/ZP1015/Desktop/linux-2.6.32.2

all:
	 make -C $(KERNELDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-
clean:
	rm -f *.o *.ko *.mod.o *.mod.c *.symvers modul*

endif
           

1、ifeq”文法是ifeq (<arg1>;, <arg2>;),功能是比較參數“arg1”和“arg2”的值是否相同。ifneq剛好相反,比較兩者的值是否不同其中有一些是我們常見或是見過的,第一個ifneq ($(KERNELRELEASE),)目前,有用處,它的由來是指在Linux源碼根目錄下的Makefile編譯核心時,KERNELRELEASE宏會被定義,那麼如果是從源碼根目錄開始的make則會将hello.o子產品編譯進核心。

KERNELDIR :=/home/ZP1015/Desktop/linux-2.6.32.2  這句是對KERNELDIR進行指派,這個變量是後面我們用到的指代核心源碼目錄用的。

2、make -C $(KERNELDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-

這句是Makefile的規則:這裡的$(MAKE)就相當于make,-C 選項的作用是指将目前工作目錄轉移到你所指定的位置。“M=”選項的作用是,當使用者需要以某個核心為基礎編譯一個外部子產品的話,需要在make modules 指令中加入“M=dir”,程式會自動到你所指定的dir目錄中查找子產品源碼,将其編譯,生成KO檔案。M不是makefile的選項,是核心根目錄下的Makefile中使用的變量

3、具體編譯過程

KERNELRELEASE:由Kernel頂層Makefile中定義。

判斷變量KERNELRELEASE與空字元是否相同,即判斷變量KERNELRELEASE的值是否為空,為空的話就進入else

第一次運作中,KERNELRELEASE沒有被定義,是以進入else

$(MAKE) -C $(KERNELDIR) M=$(PWD)

此處讀取KERNELDIR中的頂層Makefile。讀取後又傳回本目錄。繼續執行本目錄Makefile。

則此時KERNELRELEASE被定義。進入if.

if和else之間的為kbuild文法的語句.

4、兩段makefile對比分析

如何核心源碼路徑設定正确,其實兩段makefile沒有什麼差別,作用完全一緻。但是有用ifneq之後,可以確定是從核心構造系統調用的。如果核心源碼路徑設定錯誤,KERNELRELEASE沒有定義,make就沒有對象。是以建議用後面那段makefile

繼續閱讀