一、必備知識

1.1. Makefile基礎語法

如果還不熟悉Makefile語法,建議先系統的學習一下,特別是以下幾點:

(1) Makefile哪些部分包含的是shell語句:

編譯規則中的指令部分

${shell XX},var != XX中的XX部分

$(if …, XX, XX)中的XX部分

(2) 變量展開:

=(延遲賦值)、:=(立即賦值)、!=(值為shell命令)、?=(條件賦值)、+=(追加)

(3) include:將指定的其它Makefile內容,展開到當前Makefile

-f/-C:嵌套執行指定(目錄中的)Makefile

執行一個Makefile,并不是從第一行開始執行,而是從指定或默認的編譯目標開始執行(位置目標編譯規則之前的賦值語句,只在相應變量需要被使用時才會執行),其中,Makefile(包括include內容)中的第一個目標,為默認目標,如果make命令行中沒有指定編譯目標,則執行默認目標。

(4) 自動推導依賴文件

(5) 根據文件時間戳、中間文件(.d、.cmd),判斷依賴更新,決定是否需要重新編譯

(6) 重要的內置函數:

$(wildcard pattern)

$(patsubst pattern, replacement, text)

$(strip string)

$(filter pattern, text)

$(filter-out pattern, text)

$(call func, args..)

(7) 自動推導變量:

$@:編譯目標

$<:依賴列表中的第一個依賴對象

$^:依賴列表中的所有對象

$?:依賴文件列表中所有有更新的文件

Makefile教程可以參考以下這2個:

深入解析Makefile系列:https://zhuanlan.zhihu.com/p/362640343(簡約,直指核心)

跟我一起寫makefile(陳皓):https://blog.csdn.net/whitefish520/article/details/103968609(精典,超級詳細)

1.2. Kbuild內置函數

Linux內核源碼包含一套Makefile程序,本文基于Linux-5.2.5內核源碼分析,其中包括top Makefile,scripts/目錄下的Makefile、Makefile.build、Makefile.lib、Kbuild.include、Makefile.modpost、kconfig/Makefile等,以及其它目錄下的很多子Makefile,統稱為Kbuild。Kbuild是按照框架設計思路實現的,使得內核自身包含或外部提供的大量驅動模塊,只需要按照Kbuild框架的約定,各自提供一個簡單的Makefile即可編譯。

所以,理解內核或驅動文件的編譯過程,其實就是要理解Kbuild這套Makefile程序的實現邏輯,既然是程序,就免不了會定義一些函數,由于很多關鍵的流程,都使用了$(build)和$(if_changed),所以以下先單獨介紹(本文分析的Makefile內容,來自Linux-5.2.5內核源碼):

1.2.1. $(build)

◆使用形式:$(Q)$(MAKE) $(build)=xx目錄 [編譯目標]

◆build內部過程

◆build作用概括

以下是$(build)的使用形式,以及每個部分的作用:

1.2.2. $(if_changed)

◆使用形式:$(call if_changed, xx)

◆if_changed內部過程

◆if_changed作用概括

以下是$(if_changed)的使用形式,及其參數的含義:

二、編譯外部模塊

2.1. 涉及Makefile內容

2.2. 概要流程

2.3. 詳細流程

三、make menuconfig

3.1. 涉及Makefile內容

3.2. 概要流程

3.3. 詳細流程


四、Make [all/_all/modules]

4.1. 涉及Makefile內容

make命令行指定all/_all/modules目標,或者不指定目標時,是為了生成vmlinux文件,而vmlinux目標間接依賴prepare目標,且prepare目標編譯規則展開內容比較多,所以以下分開介紹:

◆vmlinux目標

◆prepare目標

4.2. 概要流程

◆vmlinux目標

◆prepare目標

4.3. 詳細流程

◆vmlinux目標

◆vmlinuz目標

◆prepare目標