一、Linux 工程目錄分析
二、頂層 Makefile 詳解
1、配置工程,生成.config配置文件:
make xxx_defconfig
會調用頂層的Makefile的 %config 規則。
第 534 行:引用 arch/arm/Makefile 這個文件,這個文件很重要, zImage、uImage 等這些文件就是由 arch/arm/Makefile 來生成的。
第 540 行:%config 規則: %通配符,當輸入“make xxx_defconfig”的時候就會匹配到%config 目標
%config: scripts_basic outputmakefile FORCE
$(Q)$(MAKE) $(build)=scripts/kconfig $@
第一步:依賴部分
目標 %config 依賴于 scripts_basic、outputmakefile、FORCE
①FORCE目標:
FORCE 在頂層 Makefile的 1610 行有如下定義:
PHONY += FORCE
FORCE:
FORCE 是沒有規則和依賴的,所以每次都會重新生成 FORCE。當 FORCE 作為其他目標的依賴時,由于 FORCE 總是被更新過的,因此依賴所在的規則總是會執行的。即將FORCE當做依賴時,對應的目標規則總是會被執行。
②scripts_basic目標:
該目標會執行以下命令:
$(Q)$(MAKE) $(build)=scripts/basic
$(Q)rm -f .tmp_quiet_recordmcount
其中:
Q是顯示方式:靜默make -s;詳細make V=1;不顯示make V=0
MAKE=make
build定義在scriptskbuild.include
build := -f $(srctree)/scripts/Makefile.build obj
展開后:
build := -f ./scripts/Makefile.build obj
展開后:
@make -f ./scripts/Makefile.build obj=scripts/basic
@rm -f .tmp_quiet_recordmcount
最終會調用文件./scripts/Makefile.build
③outputmakefile目標:
可以通過 echo 查看 KBUILD_SRC 為空:
mytest:
@echo KBUILD_SRC = $(KBUILD_SRC)
所以該目標規則沒有執行如何命令。
第二步:命令部分
目標 %config 依賴于 scripts_basic、outputmakefile、FORCE ,執行以下命令:
$(Q)$(MAKE) $(build)=scripts/kconfig $@
展開:
make -f ./scripts/Makefile.build obj=scripts/kconfig xxx_defconfig
也跟文件./scripts/Makefile.build 有關
第三步:Makefile.build
上面的分析最后指向以下兩條命令:
make -f ./scripts/Makefile.build obj=scripts/basic
make -f ./scripts/Makefile.build obj=scripts/kconfig xxx_defconfig
1、 scripts_basic 目標對應的命令:
make -f ./scripts/Makefile.build obj=scripts/basic
打開文件 scripts/Makefile.build,有如下代碼:
# Modified for U-Boot
prefix := tpl
src := $(patsubst $(prefix)/%,%,$(obj))
ifeq ($(obj),$(src))
prefix := spl
src := $(patsubst $(prefix)/%,%,$(obj))
ifeq ($(obj),$(src))
prefix := .
endif
endif
# The filename Kbuild has precedence over Makefile
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
include $(kbuild-file)
使用@echo打印各個變量值,結果如下:
src= scripts/basic
kbuild-dir = ./scripts/basic
kbuild-file = ./scripts/basic/Makefile
include ./scripts/basic/Makefile
其中src的值即為obj=scripts/basic的值,并且包含了scripts/basic/目錄下的Makefile。
make執行時未指定目標,會執行Makefile.build中的默認目標,如下:
__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y))
$(if $(KBUILD_MODULES),$(obj-m) $(modorder-target))
$(subdir-ym) $(always)
@:
其中KBUILD_BUILTIN = 1、KBUILD_MODULES = 0,展開后即為:
__build:$(builtin-target) $(lib-target) $(extra-y)) $(subdir-ym) $(always)
@:
在 scripts/Makefile.build 的默認執行目標末尾使用@echo 打印各變量值,得:
builtin-target =
lib-target =
extra-y =
subdir-ym =
always = scripts/basic/fixdep scripts/basic/bin2c
展開后只剩 always ,即 $(always) = scripts/basic/fixdep scripts/basic/bin2c,因此需要先編譯scripts/basic/fixdep.c 和 scripts/basic/bin2c.c 生成fixdep、bin2c這個兩個軟件。
2、 %config 目標對應的命令:
make -f ./scripts/Makefile.build obj=scripts/kconfig xxx_defconfig
src的值即為obj=scripts/basic的值,所以Makefile.build中各個變量值如下:
src= scripts/kconfig
kbuild-dir = ./scripts/kconfig
kbuild-file = ./scripts/kconfig/Makefile
include ./scripts/kconfig/Makefile
include包含了./scripts/kconfig目錄下的Makefile,執行make時會調用scripts/kconfig/ Makefile中的內容,此文件有如下所示內容:
%_defconfig: $(obj)/conf
$(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)
# Added for U-Boot (backward compatibility)
%_config: %_defconfig
@:
目標%_defconfig 剛好和我們輸入的 xxx_defconfig 匹配,依賴為$(obj)/conf,展開后就是 scripts/kconfig/conf,該依賴會編譯 scripts/kconfig/conf.c 生成 conf 這個軟件。
得到 scripts/kconfig/conf 以后就要執行目標%_defconfig 的命令:
$(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)
將其展開就是:
@ scripts/kconfig/conf --defconfig=arch/../configs/xxx_defconfig Kconfig
結果是將配置輸出到.config 文件中,最終生成 Linux 根目錄下的.config 文件。
2、make 生成 vmlinux、zImag、uImag 等文件
make 或 make all //編譯linux,未指定目標將執行Makefile中默認目標
_all 的依賴如下圖所示:
如果 KBUILD_EXTMOD(編譯模塊) 為空的話 _all 依賴于all,all 定義如下:
all: vmlinux
(1)、vmlinux依賴分析:
vmlinux 依賴 scripts/link-vmlinux.sh 和 $(vmlinux-deps) ,如下:
上圖第912 行定義了 vmlinux-deps,值為:
vmlinux-deps := $(KBUILD_LDS) $(KBUILD_VMLINUX_INIT) $(KBUILD_VMLINUX_MAIN)
上圖第907行:
KBUILD_LDS := arch/$(SRCARCH)/kernel/vmlinux.lds
其中 SRCARCH=arm,展開即:
KBUILD_LDS= arch/arm/kernel/vmlinux.lds
綜上所述,vmlinux 的依賴為:
scripts/link-vmlinux.sh、$(head-y) 、$(init-y)、$(core-y) 、$(libs-y) 、$(drivers-y) 、$(net-y)、arch/arm/kernel/vmlinux.lds 和 FORCE
重點來看一下
(
h
e
a
d
?
y
)
、
(init-y)、
(
c
o
r
e
?
y
)
、
(libs-y) 、
(
d
r
i
v
e
r
s
?
y
)
和
(net-y)這六個變量的值:
①head-y依賴:
head-y 定義在文件 arch/arm/Makefile 中,內容如下:
head-y := arch/arm/kernel/head$(MMUEXT).o
不使能 MMU 時 MMUEXT=-nommu,使能 MMU 時為空,因此 head-y 最終的值為:
head-y = arch/arm/kernel/head.o
②init-y、drivers-y、net-y依賴:
在頂層 Makefile 中有如下代碼:
init-y := init/
drivers-y := drivers/ sound/ firmware/
net-y := net/
......
init-y := $(patsubst %/, %/built-in.o, $(init-y))
drivers-y := $(patsubst %/, %/built-in.o, $(drivers-y))
net-y := $(patsubst %/, %/built-in.o, $(net-y))
init-y、libs-y、drivers-y 和 net-y 最終的值為:
init-y = init/built-in.o
drivers-y = drivers/built-in.o sound/built-in.o firmware/built-in.o
net-y = net/built-in.o
③lib-y依賴
libs-y 基本和 init-y 一樣,在頂層 Makefile 中存在如下代碼:
libs-y := lib/
......
libs-y1 := $(patsubst %/, %/lib.a, $(libs-y))
libs-y2 := $(patsubst %/, %/built-in.o, $(libs-y))
libs-y := $(libs-y1) $(libs-y2)
libs-y 應該等于“lib.a built-in.o”,這個只正確了一部分!因為在 arch/arm/Makefile 中會向 libs-y 中追加一些值,代碼如下:
libs-y := arch/arm/lib/ $(libs-y)
arch/arm/Makefile 將 libs-y 的值改為了:arch/arm/lib $(libs-y),展開以后為:
libs-y = arch/arm/lib lib/
libs-y 最終應該為:
libs-y = arch/arm/lib/lib.a lib/lib.a arch/arm/lib/built-in.o lib/built-in.o
④core-y依賴
core-y 和 init-y 也一樣,在頂層 Makefile 中有如下代碼:
core-y := usr/
......
core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
但是在 arch/arm/Makefile 中會對 core-y 進行追加,代碼如下:
core-$(CONFIG_FPE_NWFPE) += arch/arm/nwfpe/
core-$(CONFIG_FPE_FASTFPE) += $(FASTFPE_OBJ)
core-$(CONFIG_VFP) += arch/arm/vfp/
core-$(CONFIG_XEN) += arch/arm/xen/
core-$(CONFIG_KVM_ARM_HOST) += arch/arm/kvm/
core-$(CONFIG_VDSO) += arch/arm/vdso/
# If we have a machine-specific directory, then include it in the build.
core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
core-y += arch/arm/probes/
core-y += arch/arm/net/
core-y += arch/arm/crypto/
core-y += arch/arm/firmware/
core-y += $(machdirs) $(platdirs)
第 1~6 行:根據不同的配置向 core-y 追加不同的值,比如使能 VFP 的話就會在 .config 中有 CONFIG_VFP=y 這一行,那么 core-y 就會追加“arch/arm/vfp/”。
第 9~14 行:就是對 core-y 直接追加的值。
在頂層 Makefile 中有如下一行:
core-y := $(patsubst %/, %/built-in.o, $(core-y))
經過上述代碼的轉換,最終 core-y 的值為:
core-y = usr/built-in.o
arch/arm/vfp/built-in.o
arch/arm/vdso/built-in.o
arch/arm/kernel/built-in.o
arch/arm/mm/built-in.o
arch/arm/common/built-in.o
arch/arm/probes/built-in.o
arch/arm/net/built-in.o
arch/arm/crypto/built-in.o
arch/arm/firmware/built-in.o
arch/arm/mach-imx/built-in.o
kernel/built-in.o
mm/built-in.o
fs/built-in.o
ipc/built-in.o
security/built-in.o
crypto/built-in.o
block/built-in.o
(2)、vmlinux命令分析:
vmlinux 的依賴分析完成,接下來分析 vmlinux 執行的命令:
+$(call if_changed,link-vmlinux)
該命令最終會調用 scripts/link-vmlinux.sh 這個腳本,根據 arch/arm/kernel/vmlinux.lds 鏈接文件,將各個子目錄下的所有 built-in.o、*.a 鏈接生成 vmlinux。
(3)、vmlinux生成zImag、uImag等:
頂層Makefile中有如下定義:
include arch/$(SRCARCH)/Makefile
export KBUILD_DEFCONFIG KBUILD_KCONFIG
展開即:
include arch/arm/Makefile
在 arch/arm/Makefile 中的默認執行目標如下:
展開即:
all : zImag dtbs
arch/arm/Makefile 中還有如下定義:
BOOT_TARGETS = zImage Image xipImage bootpImage uImage
INSTALL_TARGETS = zinstall uinstall install
PHONY += bzImage $(BOOT_TARGETS) $(INSTALL_TARGETS)
$(BOOT_TARGETS): vmlinux
$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
展開即:
zImage Image xipImage bootpImage uImage: vmlinux
$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
Makefile 默認執行的目標依賴于 zImag ,要編譯 zImage,那么命令展開以后如下所示:
@ make -f ./scripts/Makefile.build obj=arch/arm/boot MACHINE=arch/arm/boot/zImage
是使用 scripts/Makefile.build 文件來完成 vmlinux 到 zImage 的轉換。
上一篇:【IMX6ULL學習筆記】八、Linux啟動流程
下一篇:【IMX6ULL學習筆記】六、U-BOOT環境變量與Linux啟動
推薦閱讀最新更新時間:2025-03-27 12:01




設計資源 培訓 開發板 精華推薦
- EspHarbor
- 具有 12V VDD 輸入的 LTC2945IUD-1 3.3V 輸入電源監視器的典型應用
- LT1070 正負降壓/升壓轉換器的典型應用
- RDR-813 - 27W USB PD 3.0,使用InnoSwitch3-Pro和威盛實驗室VP302控制器的3.3 V-11 V PPS電源(單板設計)。
- 面向汽車網絡處理的S32G參考設計2
- air_inspector
- NCP137AFCT110T2GEVB:偏置軌 LDO 穩壓器演示板
- 使用 Richtek Technology Corporation 的 RT9041D 的參考設計
- LTC3603EMSE 1.8V、2.5A 降壓穩壓器(1MHz、突發模式操作)的典型應用電路
- 1.23 至 37V DC 至 DC 單路輸出電源