zz linux 2.6.x Makefile

nux-2.6.x makefile 
  
linux-2.6.20.6/Documentation/kbuild/makefiles.txt 
  
一、             概述 
  
linux的makefile有五個部分: 
  
Makefile:頂層Makefile 
.config:內核配置文件 
arch/$(ARCH)/Makefile:體系結構相關的Makefile 
scripts/Makefile.*:通用的規則等,用於所有的kbuild Makefiles 
kbuild Makefiles:大約有500個這樣的makefile 
  
頂層Makefile讀取在內核配置過程中生成的.config文件。負責構建兩個主要的文件:vmlinux和各模塊。它還包含了一個名爲arch/$(ARCH)/Makefile的體系結構相關Makefile,這個Makefile給頂層Makefile提供了體系結構相關的信息。 
  
每個子目錄有一個kbuild Makefile,它執行上層傳入的命令。kbuild Makefile使用.config文件中的信息構建各種文件列表,供kbuild構建任何built-in或modular目標時使用。 
  
scripts/Makefile.*包含所有的定義和規則等,這些被用來和kbuild makeflie一起構建內核 
  
二、             kbuild文件 
  
kbuild Makefile中的語法。 
  
kbuild文件首選的文件名是”Makefile”,也可以用”kbuild”。如果”Makefile”和”kbuild”同時存在,則使用”kbuild”文件。 
  
1、  目標定義 
  
目標定義是kbuild Makefile的主要部分。這些行定義了要被編譯的文件、所有指定的編碼選項及所有將要遞歸進入的子目錄。 
  
最簡單的kbuild Makefile包括一行: 
  
obj-y += foo.o 
  
如果foo.o要被編譯成模塊,就用obj-m。因此,經常使用下面的模式: 
  
obj-$(CONFIG_FOO) += foo.o 
  
$(CONFIG_FOO)的值是y (for built-in)或者m(for module)。如果CONFIG_FOO既不是y也不是m,這個文件不會被編譯或鏈接 
  
2、  Built-in 對象目標 - obj-y 
  
kbuild Makefile 在$(obj-y)列表中給vmlinux指定目標文件,這個列表依賴於內核配置。 
  
kbuild 編譯所有的$(obj-y)文件,然後調用”$(LD) –r”把這些文件合併成一個built-in.o文件,之後built-in.o被頂層Makefile鏈接成vmlinux。 
  
$(obj-y)中文件的順序很重要,在這個列表中,完全相同的文件可以同時存在:第一個被鏈接到built-in.o,以後的都被忽略了。 
  
鏈接順序也很重要,因爲特定的函數(module_init() / __initcall)會在啓動期間按照它們出現的順序被調用。 
  *.c------>*.o------>build-in.o------->vmlinux
3、  可加載模塊目標 - obj-m 
  
$(obj-m)指定被編譯爲可加載內核模塊的文件。一個模塊可以是一個或多個源文件編譯生成。如果是一個源文件,kbuild makefile只是簡單的把這個文件加入$(obj-m)。如果內核模塊由多個源文件編譯生成,內核要知道你想要編譯哪些源文件,所以你必須設置變量$(<module_name>-objs)來告訴內核。 
  
eg. 
   #derivers/isdn/i4l/Makefile 
   obj-$(CONFIG_ISDN) += isdn.o 
   isdn-objs := isdn_net_lib.o isdn_v110.o isdn_common.o 
  
在這個例子中,模塊名是isdn.o。Kbuild會編譯$(isdn-objs)中列出的對像,並運行”$(LD) –r”生成isdn.o。 
  
Kbuild通過後綴-objs和-y識別用於編譯生成目標的對像。它允許Makefile使用CONFIG_符號的值來決定一個對像是否是某個目標的一部分。 
  
eg. 
              #fs/ext2/Makefile 
               obj-$(CONFIG_EXT2_FS)        += ext2.o 
              ext2-y                       := balloc.o bitmap.o 
               ext2-$(CONFIG_EXT2_FS_XATTR) += xattr.o 
  
如果CONFIG_EXT2_FS_XATTR的值爲’y’,則xattr.o就是ext2.o的一部分。 
  
4、  庫文件目標 - lib-y 
  
所有列在lib-y中的對像都被組合到一個單獨的庫中。既列在obj-y中又列在lib-y中的對像不會被包含到庫中。因爲不管怎樣,它們都是可訪問的。爲了保持一致,列在lib-m中的對像會被包含到lib.a。 
  
       Example: 
              #arch/i386/lib/Makefile 
              lib-y    := checksum.o delay.o 
  
此處基於checksum.o和delay.o創建了庫lib.a. 
  
5、  向下進入目錄 
  
一個Makefile僅負責在它自己的目錄中編譯文件。子目錄中的文件由子目錄中的Makefile負責編譯。如果你告訴了編譯系統這些子目錄,它會自動在子目錄中遞歸調用make。 
  
ext2放在了一個單獨的目錄中,在fs/目錄下的Makefile用正面的賦值告訴kbuild向下進入目錄 
  
eg: 
              #fs/Makefile 
              obj-$(CONFIG_EXT2_FS) += ext2/ 
  
如果CONFIG_EXT2_FS的值是’y’(built-in)或’m’(modular),對應的obj-變量就會被設置,kbuild向下進入ext2目錄。 
  
kbuild只是通過這個信息決定要訪問哪個目錄,子目錄中的Makefile指定什麼是modules、什麼是built-in。 
  
6、編譯flags 
  
    EXTRA_CFLAGS, EXTRA_AFLAGS, EXTRA_LDFLAGS, EXTRA_ARFLAGS 
  
所有EXTRA_變量只用在它的定義所在的那個kbuild makefile,它們被用於kbuild makefile中所有命令的執行 
  
$(EXTRA_CFLAGS)指定了用$(CC)編譯c文件時的選項。 
  
$(EXTRA_AFLAGS)是每個目錄在編譯彙編源文件時的選項。 
  
$(EXTRA_LDFLAGS) 和 $(EXTRA_ARFLAGS)是用於$(LD)和$(AR)的選項。 
  
       Example: 
              #arch/m68k/fpsp040/Makefile 
              EXTRA_LDFLAGS := -x 
  
    CFLAGS_$@, AFLAGS_$@ 
  
CFLAGS_$@ 和AFLAGS_$@ 只在當前kbuild makefile的命令中使用。 
  
$(CFLAGS_$@)爲$(CC)指定了每個文件的選項。$@指定了使用它的文件。 
  
       Example: 
              # drivers/scsi/Makefile 
              CFLAGS_aha152x.o =   -DAHA152X_STAT -DAUTOCONF 
              CFLAGS_gdth.o    = # -DDEBUG_GDTH=2 -D__SERIAL__ -D__COM2__ / 
                                 -DGDTH_STATISTICS 
              CFLAGS_seagate.o =   -DARBITRATE -DPARITY -DSEAGATE_USE_ASM 
  
這三行爲aha152.o、gdth.o和seagate.o指定了編譯選項。 
  
$(AFLAGS_$@)對於彙編源文件有類似的作用 
  
       Example: 
              # arch/arm/kernel/Makefile 
              AFLAGS_head-armv.o := -DTEXTADDR=$(TEXTADDR) -traditional 
              AFLAGS_head-armo.o := -DTEXTADDR=$(TEXTADDR) –traditional 
  
8、對依賴的追蹤 
  
Kbuild追蹤下面的依賴: 
  
1)、所有必備的文件(*.c和*.h) 
2)、用在所有必備文件中的CONFIG_選項 
3)、用於編譯目標的命令行 
  
因此,如果改變了$(CC)的選項,所有受影響的文件都會被重新編譯。 
  
9、特殊規則 
  
如果kbuild的基本組織沒提供必要的支持,特殊規則就會被使用。典型的例子就是在編譯過程中產生頭文件。另一個例子就是體系結構相關的Makefile,爲了準備啓動映像,它需要特殊的規則。 
  
Kbuild不在Makefile所在的目錄中執行,所以所有的特殊規則應拱必備文件和目標文件的相對路徑。定義特殊規則時要用到兩個變量: 
  
$(src) 
$(src)是指向Makefile所在目錄的相對路徑。涉及到源目錄樹中的文件總會用到$(src)。 
  
$(obj) 
$(obj)是指向保存目標的目錄的相對路徑。涉及到生成文件時總會用到$(obj)。 
  
       Example: 
              #drivers/scsi/Makefile 
              $(obj)/53c8xx_d.h: $(src)/53c7,8xx.scr $(src)/script_asm.pl 
                     $(CPP) -DCHIP=810 - < $< | ... $(src)/script_asm.pl 
  
10、$(CC)支持函數 
  
內核可能用好幾個不同版本的$(CC)進行編譯,每個版本都支持一組唯一的特徵和選項。kbuild提供了基本的支持用於檢測有效的$(CC)選項。 
  
as-option 
as-option用於檢測$(CC)是否支持給定式的選項(在編譯彙編文件*.S時)。如果不支持第一個選項,將會指定一個可供選擇的第二選項。 
  
       Example: 
              #arch/sh/Makefile 
              cflags-y += $(call as-option,-Wa$(comma)-isa=$(isa-y),) 
  
在上例中,如果$(CC)支持-Wa$(comma)-isa=$(isa-y),cflags-y就等於-Wa$(comma)-isa=$(isa-y)。第二個參數是可選的,如果 不支持第一個參數,而又提供了第二個參數,那麼第二個參數就會被使用。 
  
ld-option 
ld-option用於在鏈接時檢測$(CC)是否支持給定的選項。如果不支持第一個,可能會指定一個可選的第二選項。 
  
as-instr 
as-instr檢測彙編器是否報告一個特殊指令並輸出選項1或選項2。 
  
cc-option 
cc-option用來檢測$(CC)是否支持一個給定式的選項,並且不支持一個可選的第二選項。 
  
       Example: 
              #arch/i386/Makefile 
              cflags-y += $(call cc-option,-march=pentium-mmx,-march=i586) 
  
上例中,如果$(CC)支持,cflags-y會被賦值爲選項-march=pentium-mmx,否則賦值爲-march=i586。對於cc-option,第二個參數是可選的,如果被優化了,當不支持第一個選項時,cflags-y將不會被賦值。 
  
cc-option-yn 
cc-option-yn檢測gcc是否支持一個給定的選項,如果支持,返回’y’,否則,返回’n’。 
  
       Example: 
              #arch/ppc/Makefile 
              biarch := $(call cc-option-yn, -m32) 
              aflags-$(biarch) += -a32 
              cflags-$(biarch) += -m32 
  
cc-option-align 
gcc 3.0及其以上的版本改變了選項的類型,這些選項用於指定函數、循環等的排列。當被用作排列選項的前綴時,$(cc-option-align)會選擇正確的前綴 
  
       gcc < 3.00 
              cc-option-align = -malign 
       gcc >= 3.00 
              cc-option-align = -falign 
  
       Example: 
              CFLAGS += $(cc-option-align)-functions=4 
  
上例中,gcc >=3.00時,使用-falign-functions=4。gcc < 3.00時,使用用-malign-functions=4. 
  
cc-version 
cc-version返回$(CC)編譯器版本的數字版本。 
  
cc-ifversion 
cc-ifversion檢測$(CC)的版本,如果版本表達式爲真,其返回值就是最後一個參數。 
  
三、             主機程序支持 
  
Kbuild支持在主機上編譯生成可執行文件,用於編譯階段。爲了使用一個主機可執行程序,需要如下兩步: 
  
第一步,告訴kbuild存在一個主機程序。這是利用變量hostprogs-y來做的 
  
第二步,給這個可執行程序添加一個直接的依賴。可以用兩種方法做到:在規則中添加依賴或者利用變量$(always)添加。 
  
這兩種可能會在下面描述。 
  
1、  簡單主機程序 
  
有些情況下,需要在主機上編譯並運行一個程序。下面這行告訴kbuild程序bin2hex將在主機上被編譯。 
  
       Example: 
              hostprogs-y := bin2hex 
  
上例中,kbuild假定bin2hex是由當前Makefile所在目錄中的一個c文件bin2hex.c編譯生成的。 
  
2、  組合主機程序 
  
主機程序可以通過組合目標來構建。$(<executable>-objs)列出了所有對像,這些對像被鏈接成最終的可執行程序。 
  
Example: 
              #scripts/lxdialog/Makefile 
              hostprogs-y   := lxdialog 
              lxdialog-objs := checklist.o lxdialog.o 
  
3、  定義共享庫 
  
Kbuild提供對共享庫的支持,但用法會受限制。下例中,用libkconfig.so共享庫鏈接生成可執行文件conf. 
  
       Example: 
              #scripts/kconfig/Makefile 
              hostprogs-y     := conf 
              conf-objs       := conf.o libkconfig.so 
              libkconfig-objs := expr.o type.o 
  
共享庫總是需要一個對應的-objs行,上例中libkconfig共享由expr.o和type.o組合而成。expr.o和type.o會被編譯成位置無關代碼,並被鏈接成共享庫libkconfig.so。c++不支持共享庫。 
  
4、  把c++用於主機程序 
  
kbuild提供了對c++主機程序的支持。 
  
       Example: 
              #scripts/kconfig/Makefile 
              hostprogs-y   := qconf 
              qconf-cxxobjs := qconf.o 
  
上例中可執行程序由c++文件qconf.cc(由$(qconf-cxxobjs)標識)組合生成. 
  
如果qconf由.c和.cc文件混合組成,那就要再添加一行 
  
  
       Example: 
              #scripts/kconfig/Makefile 
              hostprogs-y   := qconf 
              qconf-cxxobjs := qconf.o 
              qconf-objs    := check.o 
  
5、  爲主機程序控制編譯選項 
  
編譯主機程序時,會用$(HOSTCC),並傳遞由$(HOSTCFLAGS)指定的選項。爲了設置可以影響所有在那個Makefile中創建的主機程序的標記,可以使用變量HOST_EXTRACFLAGS。 
  
       Example: 
              #scripts/lxdialog/Makefile 
              HOST_EXTRACFLAGS += -I/usr/include/ncurses 
  
給單個文件設置特殊的標記: 
  
       Example: 
              #arch/ppc64/boot/Makefile 
              HOSTCFLAGS_piggyback.o := -DKERNELBASE=$(KERNELBASE) 
  
也可以給鏈接器指定附加選項 
  
       Example: 
              #scripts/kconfig/Makefile 
              HOSTLOADLIBES_qconf := -L$(QTDIR)/lib 
  
6、  何時主機程序被編譯 
  
只有在主機程序被當作依賴引用時,Kbuild纔會編譯主機程序 
  
有兩種方法: 
  
1)、在一個特殊的規則中直接列出依賴 
  
       Example: 
              #drivers/pci/Makefile 
              hostprogs-y := gen-devlist 
              $(obj)/devlist.h: $(src)/pci.ids $(obj)/gen-devlist 
                     ( cd $(obj); ./gen-devlist ) < $< 
  
在$(obj)/gen-devlist被更新之前,不會編譯生成$(obj)/devlist.h。注意,在特殊規則中引用主機程序必須加前綴$(obj). 
  
2)、使用$(always) 
  
當沒有合適的特殊規則,而在進入makefile時主機程序要被編譯,這時就要用$(always)變量。 
  
       Example: 
              #scripts/lxdialog/Makefile 
              hostprogs-y   := lxdialog 
              always        := $(hostprogs-y) 
  
這裏告訴kbuild,即使沒有在任何規則中被引用,也編譯lxdialog。 
  
7、  使用hostprog-$(CONFIG_FOO) 
  
Kbuild文件中一個典型的模式如下 
  
       Example: 
              #scripts/Makefile 
              hostprogs-$(CONFIG_KALLSYMS) += kallsyms 
  
Kbuild知道’y’對應built-in,’m’對應module。所以如果一個配置符號賦值爲’m’,kbuild依然會編譯生成二進制碼。換句話說,kbuild把hostprogs-m和hostprogs-y作同樣處理。在沒有包括CONFIG符號時,只推薦使用hostprogs-y. 
  
四、             Kbuild的清除結構組織 
  
“make clean”會刪除大部分生成的文件,這些文件在編譯內核的目錄樹中。包括主機程序。Kbuild知道列在$(hostprogs-y), $(hostprogs-m), $(always),$(extra-y) 和 $(targets)中的目標。它們都會在”make clean”時被刪除。符合”*.[oas]”、”*.ko”模式的文件,加上一些由kbuild生成的附加文件,都會在執行”make clean”時,從整個內核源碼樹中被刪除。 
  
注意: 
  
1)、arch/$(ARCH)/Makefile不能使用”subdir-”,因爲這個文件被包含在頂層Makefile中,而kbuild結構組織在那裏是不運作的。 
  
2)、”make lcean”時,所有下個列在core-y, libs-y, drivers-y 和 net-y中的目錄都會被訪問。 
  
五、             體系結構Makefile 
  
在開始向下進入各單獨的目錄前,頂層目錄設置了環境變量,並做了準備工作。頂層Makefile包含了通用的部分,而arch/$(ARCH)/Makefile爲上述體系結構設置kbuild所要用的內容。因此arch/$(ARCH)/Makefile設置了大量的變量並定義少量的目標。 
  
執行kbuild時,會有以下步驟: 
  
1)、內核的配置=>生成.config 
  
2)、在include/linux/version.h中存儲內核版本 
  
3)、include/asm到include/asm-$(ARCH)的符號鏈接 
  
4)、更新所有目標的其他依賴:――附加的依賴在arch/$(ARCH)/Makefile中指定。 
  
5)、遞歸向下進入所有列在init-* core* drivers-* net-* libs-*中的目錄,並編譯所有目標。――上述變量的值在arch/$(ARCH)/Makefile中擴展
  
6)、然後所有目標文件被鏈接,生成的文件vmlinux放在obj目錄樹的根目錄中。最先被鏈接的目標列在head-y中,head-y由arch/$(ARCH)/Makefile賦值。 
  
7)、最後,體系結構相關的部分做了所有必需的處理,並編譯生成了最終的啓動映像。包括編譯引導記錄,準備initrd映像及相關文件。 
  
1、  設置變量,把編譯轉向具體某個體系結構 
  
LDFLAGS Generic $(LD) options 
  
調用鏈接器時用到的標記。通常指定emulation就足夠了 
  
注意:EXTRA_LDFLAGS和LDFLAGS_$@可用來進一步定製用到的標記。後面會提到。 
  
LDFLAGS_MODULE 鏈接模塊時$(LD)的選項。默認是”-r”,用於生成可重定位輸出文件。 
  
LDFLAGS_vmlinux 鏈接vmlinux時$(LD)用到的選項。LDFLAGS_vmlinux要用到LDFLAGS_$@的支持。 
  
OBJCOPYFLAGS objcopy 標記。 
  
當用$(call if_changed,objcopy)轉換.o文件時,會用到由OBJCOPYFLAGS指定的標記。$(call if_changed,objcopy)通常用來生成一個基於vmlinux的原始的二進制文件。 
  
       Example: 
              #arch/s390/Makefile 
              OBJCOPYFLAGS := -O binary 
  
              #arch/s390/boot/Makefile 
              $(obj)/image: vmlinux FORCE 
                     $(call if_changed,objcopy) 
  
AFLAGS  用於$(AS)的彙編程序標記 
  
默認值在頂層Makefile,各體系結構中根據情況做些添加修改 
  
CFLAGS $(CC)編譯標記 
  
默認值在頂層Makefile,各體系結構中根據情況做些添加修改 
  
CFLAGS_KERNEL  爲built-in指定的$(CC)選項。$(CFLAGS_KERNEL)包含編譯固定內核代碼時用的額外的編譯標記 
  
CFLAGS_MODULE $(CC)編譯模塊時用到的編譯選項,$( CFLAGS_MODULE)包含編譯可加載內核模塊代碼時用的額外的編譯標記 
  
2、  向archprepare添加依賴 
  
archprepare:在開始向下進入各子目錄前,用規則列出需要編譯的依賴。 
  
這個經常用在包含彙編常量的頭文件 
  
              Example: 
              #arch/arm/Makefile 
              archprepare: maketools 
  
上例中,maketools在向下進入各子目錄前會被處理好 
  
3、  向下進入時,列出要訪問的目錄 
  
體系結構相關Makefile和頂層Makefile結合定義了一些變量,這些變量指定指出怎樣編譯vmlinux文件。對於模塊,沒有對應的體系結構相關部分;模塊編譯機制是完全體系結構無關的。 
  
head-y, init-y, core-y, libs-y, drivers-y, net-y 
  
$(head-y)列出最先被鏈接到vmlinux的目標。 
  
$(libs-y)列出了存放lib.a歸檔文件的目錄。 
  
其他的列出了存放built-in.o目標文件的目錄。 
  
$(init-y)目標放在$(head-y)後面,其他的按下面順序排列: 
  
$(core-y), $(libs-y), $(drivers-y), $(net-y). 
  
頂層Makefile定義了所有通用目錄的值,而arch/$(ARCH)/Makefile只添加了體系結構相關的目錄。 
  
       Example: 
              #arch/sparc64/Makefile 
              core-y += arch/sparc64/kernel/ 
              libs-y += arch/sparc64/prom/ arch/sparc64/lib/ 
              drivers-$(CONFIG_OPROFILE)  += arch/sparc64/oprofile/ 
  
4、  體系結構相關引導映像 
  
體系結構相關Makefile指定生成vmlinux文件的目標,然後壓縮vmlinux,把它封裝成引導代碼,並把最終的文件複製到某個位置。 
  
通常把所有附加處理放在arch/$(ARCH)/下的boot/目錄中。 
  
Kbuild並不提供智能的方法來支持編譯在boot/目錄中指定的目標。因此,arch/$(ARCH)/Makefile要手工調用make在boot/目錄中編譯目標。 
  
       Example: 
              #arch/i386/Makefile 
              boot := arch/i386/boot 
              bzImage: vmlinux 
                     $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ 
  
推薦用"$(Q)$(MAKE) $(build)=<dir>"在子目錄中調用make。 
  
沒有命名體系結構相關目標的規則,但是執行”make help”會列出所有相關的目標。要支持這個,必須定義$(archelp) 
  
       Example: 
              #arch/i386/Makefile 
              define archhelp 
                echo  '* bzImage      - Image (arch/$(ARCH)/boot/bzImage)' 
              endif 
  
如果不帶參數執行make,遇到的第一個目標會被編譯。頂層Makefile中第一個出現的目標是all: 。 
  
每種體系結構總要默認的編譯一個可引導映像。執行”make help”時,默認目標用”*”突出顯示。給all:添加一個新的依賴來選擇不同於vmlinux的默認目標 
  
       Example: 
              #arch/i386/Makefile 
              all: bzImage 
  
5、  編譯非內核目標 
  
extra-y 
  
extra-y指定了在當前目標下創建的附加目標, obj-*指定的目標除外。 
  
有兩種情況要列出extra-y中所有的目標: 
  
1)、讓kbuild能夠檢測命令行的改變――使用$(call if_changed,xxx)時 
  
2)、執行”make clean”時,kbuild知道要刪除什麼文件。 
  
       Example: 
              #arch/i386/kernel/Makefile 
              extra-y := head.o init_task.o 
  
上例中,用extra-y列出需要被編譯但不用鏈接到built-in.o中的目標文件 
  
6、  對編譯引導映像有用的命令 
  
Kbuild提供了少量的宏,這些宏在編譯引導映像時很有用。 
  
if_changed 
  
if_changed是以下命令用到的基本組織結構。 
  
       Usage: 
              target: source(s) FORCE 
                     $(call if_changed,ld/objcopy/gzip) 
  
在求這個規則的值時,會檢查是否有文件需要更新,或者因爲最後一次調用使得命令行已經改變。接下來,如果可執行程序的選項被改變了,會強制進行重編譯。 
  
任何使用if_changed的目標必須在$(targets)中列出,否則命令行檢測會失敗,目標總會被編譯。 
  
注意,忘記依賴是一個典型的錯誤。另外一個常見的缺陷是空格有時也很重要,例如,下面會出錯(注意逗號後的空格): 
  
              target: source(s) FORCE 
       #WRONG!#   $(call if_changed, ld/objcopy/gzip) 
  
ld 
  
鏈接目標。通常會用LDFLAGS_$@爲ld設置特定選項 
  
objcopy 
  
拷貝二進制碼,通常在arch/$(ARCH)/Makefile中指定OBJCOPYFLAGS。可以用OBJCOPYFLAGS_$@設置附加選項。 
  
gzip 
  
壓縮目標。最大限度壓縮目標。 
  
       Example: 
              #arch/i386/boot/Makefile 
              LDFLAGS_bootsect := -Ttext 0x0 -s --oformat binary 
              LDFLAGS_setup    := -Ttext 0x0 -s --oformat binary -e begtext 
  
              targets += setup setup.o bootsect bootsect.o 
              $(obj)/setup $(obj)/bootsect: %: %.o FORCE 
                     $(call if_changed,ld) 
  
$(targets)被賦予了所有潛在的目標,kbuild會通過它知道目標並進行如下操作: 
1)、檢查命令行的改變 
2)在make clean時刪除目標 
  
注意:忘記”target :=”賦值操作是常見的錯誤,這將導致目標文件無條件重新編譯。 
  
7、  自定義kbuild命令 
  
在KBUILD_VERBOSE=0的情況下執行kbuild,只有一個命令的簡寫正常顯示。 
  
kbuild需要設置兩個變量來打開自定義命令的這種行爲: 
  
quiet_cmd_<command> -- 要被回顯的 
     cmd_<command> -- 要執行的命令 
                                                                                                                          
       Example: 
              # 
              quiet_cmd_image = BUILD   $@ 
                    cmd_image = $(obj)/tools/build $(BUILDFLAGS) / 
                                                   $(obj)/vmlinux.bin > $@ 
  
              targets += bzImage 
              $(obj)/bzImage: $(obj)/vmlinux.bin $(obj)/tools/build FORCE 
                     $(call if_changed,image) 
                     @echo 'Kernel: $@ is ready' 
  
當更新目標$(obj)/bzImage時, 
  
       BUILD    arch/i386/boot/bzImage 
  
會在”make KBUILD_VERBOSE=0”時顯示。 
  
8、  預處理鏈接腳本 
  
當編譯vmlinux映像時,使用arch/$(ARCH)/kernel/vmlinux.lds這個鏈接腳本。這個腳本是同一目標下文件vmlinux.lds.S的預處理變量。kbuild知道.lds文件,幷包含了一個*lds.S到*lds的規則 
  
       Example: 
              #arch/i386/kernel/Makefile 
              always := vmlinux.lds 
  
              #Makefile 
              export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH) 
  
對$(always)的賦值告訴kbuild編譯目標vmlinux.lds。對$( CPPFLAGS_vmlinux.lds)的賦值告訴kbuild在編譯目標vmlinux.lds時使用指定的選項。 
  
編譯*.lds目標時,kbuild使用下面的變量: 
       CPPFLAGS    : 在頂層Makefile中設置 
       EXTRA_CPPFLAGS     : 可能在 kbuild makefile中設置 
       CPPFLAGS_$(@F)  : 目標相關標記. 注意,在這個賦值中使用全名 
  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章