linux kernel makefile 分析 - 3
上一篇: https://www.cnblogs.com/zhangzhiwei122/p/16025969.html
背景說明
版本:
5.10.0 - 下面分析中 使用的行號,都是 參考 這個 版本的 Makefile 。
線上瀏覽: https://lxr.missinglinkelectronics.com/linux/Makefile
使用場景:
在原始碼資料夾下面建立一個build 資料夾,然後使用 O=build
mkdir build
make O=build
191 ~ 1949 部分內容分解
1、 192 ~ 249 設定了 一些變數
2、251 ~ 322 判斷編譯型別,
多目標:
mixed-build (混合多目標)
單目標:
config-build (config 型別目標,比如 make menuconfig )
非config 型別的目標。
need-config ( 需要 依賴 .config檔案的)
may-sync-config (可以使用 .config檔案更新
single-build ( 單獨編譯一個目錄或一個檔案,舉例 make kernel/bound.s
3、mixed-build 為 1 時的處理(即 按照順序,為每個目標啟動 一個 sub make ,將多目標轉換為 sub make 的單目標)
4、單目標環境設定
5、config 型別的單目標處理
6、非config 型別的單目標處理 ( 本文不涉及,後面分析)
1、 192 ~ 249 設定了 一些變數
1.1 198 ~ 213 KBUILD_CHECKSRC 預設為 0 ,可以通過命令列make C=1 或make C=2 設定
208ifeq ("$(origin C)", "command line") 209 KBUILD_CHECKSRC = $(C) 210endif 211ifndef KBUILD_CHECKSRC 212 KBUILD_CHECKSRC = 0 213endif
1.2 215 ~ 226 KBUILD_EXTMOD 和 extmod-prefix ,預設為空,如果是是 make M=dir 編譯外部模組時,這兩個才有值。
215# Use make M=dir or set the environment variable KBUILD_EXTMOD to specify the 216# directory of external module to build. Setting M= takes precedence. 217ifeq ("$(origin M)", "command line") 218 KBUILD_EXTMOD := $(M) 219endif 220 221$(if $(word 2, $(KBUILD_EXTMOD)), \ 222 $(error building multiple external modules is not supported)) 223 224export KBUILD_CHECKSRC KBUILD_EXTMOD 225 226extmod-prefix = $(if $(KBUILD_EXTMOD),$(KBUILD_EXTMOD)/)
1.3 228 ~ 248 build_out_of_srctree srctree objtree VPATH 設定(依賴 首次 進入 export 出來的 abs_srctree 和 abs_objtree )
228ifeq ($(abs_srctree),$(abs_objtree)) 229 # building in the source tree 230 srctree := . 231 building_out_of_srctree := 232else 233 ifeq ($(abs_srctree)/,$(dir $(abs_objtree))) 234 # building in a subdirectory of the source tree 235 srctree := .. 236 else 237 srctree := $(abs_srctree) 238 endif 239 building_out_of_srctree := 1 240endif 241 242ifneq ($(KBUILD_ABS_SRCTREE),) 243srctree := $(abs_srctree) 244endif 245 246objtree := . 247VPATH := $(srctree) 248 249export building_out_of_srctree srctree objtree VPATH
2、251 ~ 322 判斷編譯型別
通過 5 個變數 mixed-build config-build need-config may-sync-config single-build 來控制。
2.1 259 ~ 269 對 可能出現的目標進行了歸類。
clean-targets ,clean 目標,包含 %clean mrproper cleandocs
no-dot-config-targets 不依賴 .config 檔案的目標. 舉例: $(clean-targets) 不依賴 .config 檔案 make help 不需要依賴 .config 檔案
no-sync-config-targets 不需要使用 .config 來更新 include/config/auto.conf 等檔案的目標,舉例: $(no-dot-config-targets) (它都不依賴 .config,自然...... ) %install kernelrelease
single-targets 單個檔案或資料夾作目標,採用統配符。 .a 結尾的, .s 結尾的 / 結尾的, 等等
259version_h := include/generated/uapi/linux/version.h 260old_version_h := include/linux/version.h 261 262clean-targets := %clean mrproper cleandocs 263no-dot-config-targets := $(clean-targets) \ 264 cscope gtags TAGS tags help% %docs check% coccicheck \ 265 $(version_h) headers headers_% archheaders archscripts \ 266 %asm-generic kernelversion %src-pkg dt_binding_check \ 267 outputmakefile 268no-sync-config-targets := $(no-dot-config-targets) %install kernelrelease 269single-targets := %.a %.i %.ko %.lds %.ll %.lst %.mod %.o %.s %.symtypes %/
271 ~ 275 設定 了這些變數的預設值。 預設值相當於選擇了 非config 型別的單目標,它 需要 .config 檔案,可以使用 .config 檔案來更新 include/config/auto.conf 等檔案。
271config-build := 272mixed-build := 273need-config := 1 274may-sync-config := 1 275single-build :=
need-config 變數
預設為1
277 ~ 281 檢查是否需要把它置為空。
什麼情況下置空呢? 兩個條件同時滿足:
a: make cmd goals 指定了 no-dot-config-targets目標,有這樣的目標【即說明 命令列上面指定了目標;如果命令列沒指定目標,還是需要 config的,即need-config = 1】
b: 命令列上目錄只有 no-dot-config-targets目標
277ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),) 278 ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),) 279 need-config := 280 endif 281endif 282 |
may-sync-config
預設為 1
283 ~ 291 行之間計算它的新值
兩種情況下會將它置空
a: 命令列上指定了目標,且指定的目標只有 no-sync-config-targets . may-sync-config 需要置空。283 ~ 287行。
b: KBUILD_EXTMOD 不為空【即,使用此Makefile 編譯 外部模組,不能更新 include/config.auto.conf 】,may-sync-config 需要置空。289 ~ 291 行。
283ifneq ($(filter $(no-sync-config-targets), $(MAKECMDGOALS)),) 284 ifeq ($(filter-out $(no-sync-config-targets), $(MAKECMDGOALS)),) 285 may-sync-config := 286 endif 287endif 288 289ifneq ($(KBUILD_EXTMOD),) 290 may-sync-config := 291endif |
config-build
預設為空
下列兩個條件同時滿足時,置為 1
a: KBUILD_EXTMOD 為空,即表示在編譯核心(而非驅動模組),且
b:make cmd goals 裡面的目標 包含 config 結尾 (比如 menuconfig,silentconfig,defconfig etc)
single-build
預設為空
命令列裡面指定了 single-targets 時,置為1.
single-targets 是什麼?即是單獨的一個目標檔案,或目標資料夾
269 行有定義
269single-targets := %.a %.i %.ko %.lds %.ll %.lst %.mod %.o %.s %.symtypes %/ |
舉例: make kernel/bound.s
只生成目標 kernel/bound.s
mixed-build
預設為空
下來情況之一,會置為 1
a: make cmd goals 裡面指定了 %config + 其他目標。293 ~ 300 行
b: make cmd goals 指定了 single targets + 其他目標 302 ~ 308 行
c: make cmd goals 指定了 clean targets + 其他目標 310 ~ 315 行
d: make 同時指定 install + modules_install 目標 317 ~ 322行
293ifeq ($(KBUILD_EXTMOD),) 294 ifneq ($(filter %config,$(MAKECMDGOALS)),) 295 config-build := 1 296 ifneq ($(words $(MAKECMDGOALS)),1) 297 mixed-build := 1 298 endif 299 endif 300endif 301 302# We cannot build single targets and the others at the same time 303ifneq ($(filter $(single-targets), $(MAKECMDGOALS)),) 304 single-build := 1 305 ifneq ($(filter-out $(single-targets), $(MAKECMDGOALS)),) 306 mixed-build := 1 307 endif 308endif 309 310# For "make -j clean all", "make -j mrproper defconfig all", etc. 311ifneq ($(filter $(clean-targets),$(MAKECMDGOALS)),) 312 ifneq ($(filter-out $(clean-targets),$(MAKECMDGOALS)),) 313 mixed-build := 1 314 endif 315endif 316 317# install and modules_install need also be processed one by one 318ifneq ($(filter install,$(MAKECMDGOALS)),) 319 ifneq ($(filter modules_install,$(MAKECMDGOALS)),) 320 mixed-build := 1 321 endif 322endif |
3、324 ~ 339 mixed-build 為 1 時的處理(單目標時,這段不可見)
324ifdef mixed-build 325# =========================================================================== 326# We're called with mixed targets (*config and build targets). 327# Handle them one by one. 328 329PHONY += $(MAKECMDGOALS) __build_one_by_one 330 331$(MAKECMDGOALS): __build_one_by_one 332 @: 333 334__build_one_by_one: 335 $(Q)set -e; \ 336 for i in $(MAKECMDGOALS); do \ 337 $(MAKE) -f $(srctree)/Makefile $$i; \ 338 done 339 340else # !mixed-build
4、341 ~ 585 單目標環境設定
這部分 程式碼 比較多,就不貼程式碼分析了。
4.1 342 行 引入 scripts/Kbuild.include ,裡面定義了很多輔助函式 , 比如 cmd filechk if_changed
4.2 344 ~ 347 export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION
4.3 349 引入 scripts/subarch.include ,裡面包含函式判斷 編譯主機 的arch,放在 SUBARCH (替補 arch),
4.4 369 行,如果命令列沒有 指定 ARCH=xx,則 ARCH賦值為 4.3 中得到的 SUBARCH
4.5 370 ~ 394 ,由 ARCH 得到 SRCARCH 原始碼資料夾下面的 ARCH 資料夾名稱
4.6 396 ~ 403 KCONFIG_CONFIG 預設為 .config KBUILD_DEFCONFIG 預設為 defconfig CONFIG_SHELL 預設為 sh
4.7 405 ~ 424 構建編譯機器 上面的一些工具時使用 KBUILD_HOSTCFLAGS KBUILD_HOSTCXXFLAGS KBUILD_HOSTLDFLAGS KBUILD_HOSTLIBS
4.8 426 ~ 465 定義了 make 工具需要的 變數
4.9 467 ~ 519 各種 flags 變數的定義和匯出。 KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE KBUILD_CFLAGS_KERNEL KBUILD_CFLAGS_MODULE ( 5 中型別定義差別?暫未知) KBUILD_AFLAGS KBUILD_LDFLAGS
4.10 530 ~ 560 設定 config 型別單目標 和 其他 型別單目標 都依賴的 目標( 比如 outputmakefile scripts_basic ,在下面的 5 中被依賴)
4.11 562 ~ 579 處理 如果編譯器是 clang 時的情況,在 KBUILD_CFLAGS KBUILD_AFLAGS 上面追加引數,export CLANG_FLAGS .
5、config 型別單目標處理 587 ~ 603
595 include /arch/$(SRCARCH)/Makefile ,包含它是為了得到 這個 arch (比如aarch64)的預設配置檔案,放在KBUILD_DEFCONFIG中,
make defconfig 目標是 config 目標,會走到這兒,將defconfig 目標傳遞給 scripts/kconfig 目錄下的 Makefile ,它需要使用 KBUILD_DEFCONFIG 變數。
598 和 601 分開,單純是因為 601 處的 %config 無法匹配 到 598 處的 config 。如果不想要可讀性,可以合二為一,整成 %onfig 這樣的目標。
598 和 601 處,指定 config 目標依賴 outputmakefile scripts_basic ,先要完成這兩個依賴才可以 啟動下面的 sub make .
587ifdef config-build 588# =========================================================================== 589# *config targets only - make sure prerequisites are updated, and descend 590# in scripts/kconfig to make the *config target 591 592# Read arch specific Makefile to set KBUILD_DEFCONFIG as needed. 593# KBUILD_DEFCONFIG may point out an alternative default configuration 594# used for 'make defconfig' 595include arch/$(SRCARCH)/Makefile 596export KBUILD_DEFCONFIG KBUILD_KCONFIG CC_VERSION_TEXT 597 598config: outputmakefile scripts_basic FORCE 599 $(Q)$(MAKE) $(build)=scripts/kconfig $@ 600 601%config: outputmakefile scripts_basic FORCE 602 $(Q)$(MAKE) $(build)=scripts/kconfig $@ 603 604else #!config-build
6、非config 型別單目標處理
此文不涉及,後面再分析