1. 程式人生 > 其它 >linux kernel makefile 分析 - 1

linux kernel makefile 分析 - 1

背景說明

版本:

5.10.0 - 下面分析中 使用的行號,都是 參考 這個 版本的 Makefile 。

線上瀏覽: https://lxr.missinglinkelectronics.com/linux/Makefile

 

使用場景:

在原始碼資料夾下面建立一個build 資料夾,然後使用 O=build 

mkdir build

make O=build

 

三部分的框架

 

 

 

 

第一部分:1 ~ 36 行 , 1950 ~ 結束 ;  通用部分,

1、定義 VERSION  PATCHLEVEL  SUBLEVEL EXTRALEVEL  NAME 變數

2、make 命令列中如果指定了以 雙下劃線 __ 開頭的目標,則報錯。

3、定義偽目標 __all ;

4、定義 FORCE 偽目標,

6、將 PHONY 變數中的目標,都宣告為 phony 。

 

第二部分:37~ 188 行,使用  sub_make_done 不為 1 時才進入。只有第一次使用 Makefile 時,這個變數才不為 1,因為在 174 行會  設定這個變數為 1 ,並且匯出。之後啟動的 make 都得到這個變數為 1.

1、讓 make 不要使用 內建規則和內建變數。

2、處理 LC_ALL     LC_COLLATE      LC_NUMERIC。

3、GREP_OPTIONS 置為空,

4、設定 Q   quiet  KBUILD_VERBOSE 變數。

5、得到 abs_objtree 的值

6、abs_srctree - 原始碼絕對路徑

7、this_makefile 賦值

8、need-sub-make 的賦值

9  need-sub-make 為 1 ,啟動 sub make

 

191 ~ 1948 行,使用 need-sub-make 為空時進入,即 不需要啟動 sub make 時使用 191 ~ 1948 之間的內容。

本位不涉及,後面再分析

 

通用部分

1、定義 VERSION  PATCHLEVEL  SUBLEVEL EXTRALEVEL  NAME 變數

   2VERSION = 5
   3PATCHLEVEL 
= 10 4SUBLEVEL = 0 5EXTRAVERSION = 6NAME = Kleptomaniac Octopus

2、make 命令列中如果指定了以 雙下劃線 __ 開頭的目標,則報錯。 __開頭的目標都作為 內部中間目標使用。

  14$(if $(filter __%, $(MAKECMDGOALS)), \
  15        $(error targets prefixed with '__' are only for internal use))

 

3、定義偽目標 __all ;因為命令列如果沒指定目標,則Makefile 中遇到的第一個目標就是預設目標。

  17# That's our default target when none is given on the command line
  18PHONY := __all
  19__all:

4、定義 FORCE 偽目標,依賴FORCE 的目標,都需要 無條件 重新 更新。

1950PHONY += FORCE
1951FORCE:

 

6、將 PHONY 變數中的目標,都宣告為 phony 。 【宣告為 phony 目標,make 就不會 把這個目標當作檔案目標】

1953# Declare the contents of the PHONY variable as phony.  We keep that
1954# information in a variable so we can use it in if_changed and friends.
1955.PHONY: $(PHONY)

 

首次使用包含內容

1、讓 make 不要使用 內建規則和內建變數。39 ~ 41  通過設定 MAKEFLAGS=-rR實現. 154 ~ 161 如果make版本是 3.x ,設定後,不能立即生效,需要啟動sub make 才生效。

  39# Do not use make's built-in rules and variables
  40# (this increases performance and avoids hard-to-debug behaviour)
  41MAKEFLAGS += -rR

 154ifneq ($(abs_srctree),$(abs_objtree))
 155# Look for make include files relative to root of kernel src
 156#
 157# This does not become effective immediately because MAKEFLAGS is re-parsed
 158# once after the Makefile is read. We need to invoke sub-make.
 159MAKEFLAGS += --include-dir=$(abs_srctree)
 160need-sub-make := 1
 161endif

 

2、處理 LC_ALL     LC_COLLATE      LC_NUMERIC。

(  編譯機器 本身的 LC 環境可能千差萬別,kernel 中程式碼不能都考慮。換思路:kernel 中的程式碼預設一個 LC環境,在這兒的Makefile 中,將LC環境設定為kernel 程式碼需要LC 環境 )

LC_ALL 選擇 整體的 C 語言環境;  置為空。 

LC_COLLATE 選擇 排序(歸類)的環境

LC_NUMERIC 選擇 數字格式  的環境。 德國數字環境,小數點 使用 逗號。

  43# Avoid funny character set dependencies
  44unexport LC_ALL
  45LC_COLLATE=C
  46LC_NUMERIC=C
  47export LC_COLLATE LC_NUMERIC

 

3、GREP_OPTIONS 置為空,因為 這個會影響 grep 工具的輸出,kernel 編譯會用到 grep 工具。編譯機器上面 GREP_OPTIONS 影響了grep 輸出,kernel 就得不到自己想要的輸出格式或內容了,所以,這兒置為空,保證grep 輸出是 kernel 預期的內容。

  49# Avoid interference with shell env settings
  50unexport GREP_OPTIONS

4、設定 Q   quiet  KBUILD_VERBOSE 變數。

4.1  82 行 預設為  KBUILD_VERBOSE=0, , 90  91 行也就預設  Q=@ ; quiet=quiet_; 

4.2 當命令列指定了 V=1時, KBUILD_VERBOSE=1,  Q為空 ; quiet 為空;   會  輸出 執行的命令。

4.3 命令列指定   V=2時,  KBUILD_VERBOSE=2,  Q為@ ; quiet=quiet_ ; 會列印為什麼更新這個目標(但不會列印 執行的命令 )

4.2 當命令列指定了 -s 時,為silent mode , 抑制 echo cmd. 強制修改  quiet=silent_ ; ( KBUILD_VERBOSE 和 Q 依然參照 4.1   4.2    4.3  )

  72# If KBUILD_VERBOSE equals 0 then the above command will be hidden.
  73# If KBUILD_VERBOSE equals 1 then the above command is displayed.
  74# If KBUILD_VERBOSE equals 2 then give the reason why each target is rebuilt.
  75#
  76# To put more focus on warnings, be less verbose as default
  77# Use 'make V=1' to see the full commands
  78
  79ifeq ("$(origin V)", "command line")
  80  KBUILD_VERBOSE = $(V)
  81endif
  82ifndef KBUILD_VERBOSE
  83  KBUILD_VERBOSE = 0
  84endif
  85
  86ifeq ($(KBUILD_VERBOSE),1)
  87  quiet =
  88  Q =
  89else
  90  quiet=quiet_
  91  Q = @
  92endif
  93
  94# If the user is running make -s (silent mode), suppress echoing of
  95# commands
  96
  97ifneq ($(findstring s,$(filter-out --%,$(MAKEFLAGS))),)
  98  quiet=silent_
  99endif
 100
 101export quiet Q KBUILD_VERBOSE

 

5、得到 abs_objtree 的值

5.1   138 行,如果命令列 沒有使用 O=dir 指定  輸出檔案存放目錄,則 abs_objdir=$(CURDIR)

5.2  如果命令列使用了O=dir指定了,就將abs_objdir 賦值為 指定 dir 的絕對路徑(如果dir是符號連結,找到真實路徑)。具體如下:

 123 ~ 126 判斷命令列有O=dir ,設定KBUILD_OUTPUT

128 發現 KBUILD_OUTPUT 不為空,131 行賦值 abs_objtree 為指定的dir的絕對路徑

132 ~ 133 檢查 abs_objtree 不為空,如果為空(可能原因是資料夾不存在),就報錯。

136 ,如果是符號連結,轉換為真實路徑。

 123# Do we want to change the working directory?
 124ifeq ("$(origin O)", "command line")
 125  KBUILD_OUTPUT := $(O)
 126endif
 127
 128ifneq ($(KBUILD_OUTPUT),)
 129# Make's built-in functions such as $(abspath ...), $(realpath ...) cannot
 130# expand a shell special character '~'. We use a somewhat tedious way here.
 131abs_objtree := $(shell mkdir -p $(KBUILD_OUTPUT) && cd $(KBUILD_OUTPUT) && pwd)
 132$(if $(abs_objtree),, \
 133     $(error failed to create output directory "$(KBUILD_OUTPUT)"))
 134
 135# $(realpath ...) resolves symlinks
 136abs_objtree := $(realpath $(abs_objtree))
 137else
 138abs_objtree := $(CURDIR)
 139endif # ifneq ($(KBUILD_OUTPUT),)

6、abs_srctree - 原始碼絕對路徑 - 賦值並檢查(不包含空格,冒號)

 148abs_srctree := $(realpath $(dir $(lastword $(MAKEFILE_LIST))))
 149
 150ifneq ($(words $(subst :, ,$(abs_srctree))), 1)
 151$(error source directory cannot contain spaces or colons)
 152endif

7、this_makefile 賦值

163 this-makefile := $(lastword $(MAKEFILE_LIST))

8、need-sub-make 的賦值

這個預設為空。

賦值為 1 的情況有 3 中。

a:  make版本是 3.x , 需要讓 MAKEFLAGS=-rR 生效。參考 本節 1 。 

b:  abs_objtree 和 $(CURDIR) 不相同。  144 else 進入,145 行 賦值。

 141ifeq ($(abs_objtree),$(CURDIR))
 142# Suppress "Entering directory ..." unless we are changing the work directory.
 143MAKEFLAGS += --no-print-directory
 144else
 145need-sub-make := 1
 146endif

c:  abs_objtree 和 abs_srctree 不相同。 154 判斷,160 賦值。

154ifneq ($(abs_srctree),$(abs_objtree))
 155# Look for make include files relative to root of kernel src
 156#
 157# This does not become effective immediately because MAKEFLAGS is re-parsed
 158# once after the Makefile is read. We need to invoke sub-make.
 159MAKEFLAGS += --include-dir=$(abs_srctree)
 160need-sub-make := 1
 161endif

 

9  need-sub-make 為 1 ,啟動 sub make

176 行判斷,進入

178 行 宣告 __sub-make 偽目標

180 行,讓命令列目標     預設目標   __all   和  $(this-makefile) 目標都依賴 __sub-make 偽目標

184 ·~ 186 定義 __sub-make 偽目標的更新命令,啟動 下一個make 並指定makefile ,將 命令列目標也傳遞給它。

 176ifeq ($(need-sub-make),1)
 177
 178PHONY += $(MAKECMDGOALS) __sub-make
 179
 180$(filter-out $(this-makefile), $(MAKECMDGOALS)) __all: __sub-make
 181        @:
 182
 183# Invoke a second make in the output directory, passing relevant variables
 184__sub-make:
 185        $(Q)$(MAKE) -C $(abs_objtree) -f $(abs_srctree)/Makefile $(MAKECMDGOALS)
 186
 187endif # need-sub-make

 

最後一次進入包含內容

這部分內容較多,一步步慢慢來分解