Linux核心(三)

來源:互聯網
上載者:User

Linux核心的Makefile分為5個部分:
        
     Makefile                 頂層Makefile,它讀取.config檔案,並負責建立vmlinux(核心鏡像)和modules(模組檔案)。
     .config                  核心設定檔,調用make menuconfig或者make xconfig命令等配置
     arch/$(ARCH)/Makefile    核心相關,具體架構的Makefile
     scripts/Makefile.*       公用編譯規則定義檔案。所有kbuild Makefile的規則,它們包含了定義/規則等。
     kbuild Makefiles         每個子目錄都有kbuild Makefile,它們負責產生built-in或模組化目標。(注意:kbuild Makefile是指使用kbuild結構的Makefile,核心中的大多數Makefile都是kbuild Makefile。)

頂層Makefile閱讀的.config檔案,而該檔案是由核心配置程式產生的。

頂層Makefile負責製作:vmlinux(核心檔案)與modules(模組檔案)。製作的過程主要是通過遞迴向下訪問子目錄的形式完成。並根據核心設定檔確定訪問哪些子目錄。頂層Makefile要原封不動的包含一具體架構的Makefile,其名字類似於 arch/$(ARCH)/Makefile。該架構Makefile向頂層Makefile提供其架構的特別資訊。

每一個子目錄都有一個Kbuild Makefile檔案,用來執行從其上層目錄傳遞下來的命令。
Kbuild Makefile從.config檔案中提取資訊,產生Kbuild完成核心編譯所需的檔案清單。

scripts/Makefile.*包含了所有的定義、規則等資訊。這些檔案被用來編譯基於kbuild
Makefile的核心

 

 Makefile編譯流程

當使用者使用Linux的Makefile編譯核心版本時,Makefile的編譯流程如下:

         使用命令列或者圖形介面組態工具,對核心進行裁減,產生.config設定檔

         儲存核心版本資訊到 include/linux/version.h

         產生符號連結 include/asm,指向實際目錄 include/asm-$(ARCH)

         為最終目標檔案的產生進行必要的準備工作

         遞迴進入 /init 、/core、 /drivers、 /net、 /lib等目錄和其中的子目錄來編譯產生所有的目標檔案

         連結上述過程產生的目標檔案產生vmlinux,vmlinux存放在核心代碼樹的根目錄下

         最後根據 arch/$(ARCH)/Makefile檔案定義的後期編譯的處理規則建立最終的映象bootimage,包括建立引導記錄、準備initrd映象和相關處理

 

Makefile關鍵規則和定義描述

1)        目標定義

目標定義是Makefile檔案的核心部分,目標定義通知Makefile需要產生哪些目標檔案、如何根據特殊的編譯選項連結目標檔案,同時控制哪些子目錄要遞迴進入進行編譯。

這個例子Makefile檔案位於/fs/ext2目錄 :

obj-$(CONFIG_EXT2_FS) += ext2.o

ext2-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o ioctl.o namei.o super.o symlink.o

ext2-$(CONFIG_EXT2_FS_XATTR)   += xattr.o xattr_user.o xattr_trusted.o

ext2-$(CONFIG_EXT2_FS_POSIX_ACL) += acl.o

ext2-$(CONFIG_EXT2_FS_SECURITY)     += xattr_security.o

ext2-$(CONFIG_EXT2_FS_XIP) += xip.o

這表示與 ext2相關的目標檔案由 ext2-y定義的檔案清單組成,其中ext2-$(*)是由核心設定檔.config中的配置項決定,最終Makefile會在這個目錄下統一產生一個目標檔案ext2.o(由obj-$(CONFIG_EXT2_FS)決定)。其中obj-y表示為產生vmlinux檔案所需要的目標檔案集合,具體的檔案依賴於核心配置。

Makefile會編譯所有的$(obj-y)中定義的檔案,然後調用連結器將這些檔案連結到built-in.o 檔案中。最終built-in.o檔案通過頂層Makefile連結到vmlinux中。$(obj-y)的檔案順序很重要。列表檔案可以重複,檔案第一次出現時將會連結到built-in.o中,後來出現的同名檔案將會被忽略。檔案順序直接決定了他們被調用的順序。

所有包含在lib-y定義中的目標檔案都將會被編譯到該目錄下一個統一的庫檔案中。值得注意的是lib-y定義一般被限制在 lib 和arch/$(ARCH)/lib 目錄中。

體系makefile檔案和頂層makefile檔案共同定義了如何建立vmlinux檔案的規則。

     $(head-y) 列舉首先連結到vmlinux的對象檔案。
     $(libs-y) 列舉了能夠找到lib.a檔案的目錄。
     其餘的變數列舉了能夠找到內嵌對象檔案的目錄。
     $(init-y) 列舉的對象位於$(head-y)對象之後。
     然後是如下位置順序:
     $(core-y), $(libs-y), $(drivers-y) 和 $(net-y)。
     頂層makefile定義了所有通用目錄,arch/$(ARCH)/Makefile檔案只需增加體系相關的目錄。
     例如: #arch/i386/Makefile
           libs-y                   += arch/i386/lib/

          core-y                   += arch/i386/kernel/ \

                                           arch/i386/mm/ \

                                           arch/i386/$(mcore-y)/ \

                                           arch/i386/crypto/

drivers-$(CONFIG_MATH_EMULATION) += arch/i386/math-emu/

drivers-$(CONFIG_PCI)            += arch/i386/pci/

           …………………………………………

 

2)        目錄遞迴

Makefile檔案只負責目前的目錄下的目標檔案,子目錄中的檔案由子目錄中的makefile負責編譯,編譯系統使用obj-y 和obj-m來自動遞迴編譯各個子目錄中的檔案。

對於fs/Makefile:

obj-$(CONFIG_EXT2_FS) += ext2/

如果在核心設定檔.config中,CONFIG_EXT2_FS被設定為y或者m,則核心makefile會自動進入ext2目錄來進行編譯。核心 Makefile只使用這些資訊來決定是否需要編譯這個目錄,子目錄中的makefile規定哪些檔案編譯為模組,哪些檔案編譯進核心。

 

3)        依賴關係

Linux Makefile通過在編譯過程中產生的 .檔案名稱.o.cmd(比如對於main.c檔案,它對應的依賴檔案名稱為.main.o.cmd)來定義相關的依賴關係。

一般檔案的依賴關係由如下部分組成:

          所有的前期依賴檔案(包括所有相關的*.c 和 *.h)

          所有與CONFIG_選項相關的檔案

          編譯目標檔案所使用到的命令列

 

4)    特殊規則

特殊規則使用在核心編譯需要規則定義而沒有相應定義的時候。典型的例子如編譯時間標頭檔的產生規則。其他例子有體系makefile編譯引導映像的特殊規則。特殊規則寫法同普通的makefile規則。
     編譯器在makefile所在的目錄不能被執行,因此所有的特殊規則需要提供前提檔案和目標檔案的相對路徑。
     定義特殊規則時將使用到兩個變數:
     $(src): $(src)是對於makefile檔案目錄的相對路徑,當使用代碼樹中的檔案時使用該變數$(src)。
     $(obj): $(obj)是目標檔案目錄的相對路徑。組建檔案使用$(obj)變數。
     例如: #drivers/scsi/Makefile
     $(obj)/53c8xx_d.h: $(src)/53c7,8xx.scr $(src)/script_asm.pl
        $(CPP) -DCHIP=810 - < $< | ... $(src)/script_asm.pl
     這就是使用普通文法的特殊編譯規則。
     目標檔案依賴於兩個前提檔案。目標檔案的首碼是$(obj), 前提檔案的首碼是$(src)(因為它們不是組建檔案)。

5)    引導映象

體系makefile檔案定義了編譯vmlinux檔案的目標對象,將它們壓縮和封裝成引導代碼,並複製到合適的位置。這包括各種安裝命令。在Linux中 Makefile無法為所有的體繫結構提供標準化的方法,因此常需要具體硬體體繫結構下makefile提供附加處理規則。
     附加處理過程常位於arch/$(ARCH)/下的boot/目錄。
     核心編譯體系無法在boot/目錄下提供一種便捷的方法建立目標系統檔案。因此arch/$(ARCH)/Makefile要調用make命令在boot /目錄下建立目標系統檔案。建議使用的方法是在arch/$(ARCH)/Makefile中設定調用,並且使用完整路徑引用arch/$(ARCH) /boot/Makefile。
     例如: #arch/i386/Makefile
           boot := arch/i386/boot
           bzImage: vmlinux
              $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
     建議使用"$(Q)$(MAKE) $(build)=<dir>"方式在子目錄中調用make命令。
     當執行不帶參數的make命令時,將首先編譯第一個目標對象。在頂層makefile中第一個目標對象是all:。
     一個體繫結構需要定義一個預設的可引導映像。
     增加新的前提檔案給all目標可以設定不同於vmlinux的預設目標對象。
     例如: #arch/i386/Makefile
           all: bzImage
     當執行不帶參數的"make"命令時,bzImage檔案將被編譯。

6)   常用編譯命令

if_changed
        如果必要,執行傳遞的命令。
        用法:
          $(builtin-target): $(obj-y) FORCE

          $(call if_changed,link_o_target)
        當這條規則被使用時它將檢查哪些檔案需要更新,或命令列被改變。後面這種情況將迫使重新編譯編譯選項被改變的執行檔案。使用if_changed的目標對象必須列舉在$( builtin-target)中,否則命令列檢查將失敗,目標一直會編譯。

 

if_changed_dep

       如果必要,執行傳遞的命令並更新依賴檔案。

       用法:

         %.o: %.S FORCE

         $(call if_changed_dep,as_o_S)

當這條規則被使用時它將檢查哪些檔案需要更新,或命令列被改變。同時它會重新檢測依賴關係的改變並將產生新的依賴檔案。這是與if_changed命令的區別。

 

7)   定製命令

 當正常執行帶編譯命令時命令的簡簡訊息會被顯示(要想顯示詳細的命令,請在命令列中加入V=1)。要讓定製命令具有這種功能需要設定兩個變數:
      quiet_cmd_<command> - 將被顯示的內容
      cmd_<command>      - 被執行的命令
      例如: #
           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'
     執行make命令編譯$(obj)/bzImage目標時將顯示:
     BUILD   arch/i386/boot/bzImage

 

8)   預先處理連結指令碼

當編譯vmlinux映像時將使用arch/$(ARCH)/kernel/vmlinux.lds連結指令碼。
        相同目錄下的vmlinux.lds.S檔案是這個指令碼預先處理的變體。核心編譯系統知曉.lds檔案。並使用規則*lds.S -> *lds。
        例如: #arch/i386/kernel/Makefile
           always := vmlinux.lds
           #Makefile
           export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH)
        $(always)指派陳述式告訴編譯系統編譯目標是vmlinux.lds。$(CPPFLAGS_vmlinux.lds)

指派陳述式告訴編譯系統編譯vmlinux.lds目標的編譯選項。
        編譯*.lds時將使用到下面這些變數:
        CPPFLAGS      : 定義在頂層Makefile
        EXTRA_CPPFLAGS      : 可以設定在編譯的makefile檔案中
        CPPFLAGS_$(@F) : 目標編譯選項。注意要使用檔案全名。

 

9)        主機輔助程式的編譯

核心編譯系統支援在編譯階段編譯主機可執行程式。為了使用主機程式需要兩個步驟:第一個步驟使用hostprogs-y變數告訴核心編譯系統有主機程式可用。第二步給主機程式添加潛在的依賴關係。有兩種方法,在規則中增加依賴關係或使用$(always)變數。

 

10)     Clean機制

clean命令清除在編譯核心產生的大部分檔案,例如主機程式,列舉在 $(hostprogs-y)、$(hostprogs-m)、$(always)、$(extra-y)和$(targets)中目標檔案都將被刪除。代碼目錄數中的"*.[oas]"、"*.ko"檔案和一些由編譯系統產生的附加檔案也將被刪除。
  附加檔案可以使用$(clean-files)進行定義。
     例如: #drivers/pci/Makefile
           clean-files := devlist.h classlist.h
當執行"make clean"命令時, "devlist.h classlist.h"兩個檔案將被刪除。核心編譯系統預設這些檔案與makefile具有相同的相對路徑,否則需要設定以'/'開頭的絕對路徑。
  刪除整個目錄使用以下方式:
  例如: #scripts/package/Makefile
     clean-dirs := $(objtree)/debian/
  這樣就將刪除包括子目錄在內的整個debian目錄。如果不使用以'/'開頭的絕對路徑核心編譯系統見預設使用相對路徑。
  通常核心編譯系統根據"obj-* := dir/"進入子目錄,但是在體系makefile中需要顯式使用如下方式:
     例如: #arch/i386/boot/Makefile
           subdir- := compressed/
  上面指派陳述式指示編譯系統執行"make clean"命令時進入compressed/目錄。
  在編譯最終的引導映像檔案的makefile中有一個可選的目標對象名稱是archclean。
     例如: #arch/i386/Makefile
           archclean:
              $(Q)$(MAKE) $(clean)=arch/i386/boot
  當執行"make clean"時編譯器進入arch/i386/boot,arch/i386/boot中的makefile檔案可以使用subdir-標識進入更下層的目錄。
  注意1: arch/$(ARCH)/Makefile不能使用"subdir-",因為它被包含在頂層makefile檔案中,在這個位置編譯機制是不起作用的。
  注意2: 所有列舉在core-y、libs-y、drivers-y和net-y中的目錄將被"make clean"命令清除。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.