1. Top-level makefile tracking:
Find the vmlinux target
# Vmlinux image-including updated kernel symbols
Vmlinux: $ (vmlinux-LDS) $ (vmlinux-init) $ (vmlinux-Main) $ (kallsyms. O) Force
Ifdef config_headers_check
$ (Q) $ (make)-F $ (srctree)/makefile headers_check
Endif
$ (Call if_changed_rule, vmlinux __)
$ (Q) $ (make)-F $ (srctree)/scripts/makefile. modpost $ @
$ (Q) Rm-F. old_version
@ Echo "================================== vmlinux ================ ======================"
@ Echo $ (vmlinux-LDS) $ (vmlinux-init) $ (vmlinux-Main) $ (kallsyms. O)
@ CP vmlinux. Full
Find vmlinux-init:
Vmlinux-init: = $ (Head-y) $ (init-y)
Head-Y is a machine-related variable, defined in makefile in arch:
Head-Y: = ARCH/MIPS/kernel/head. o arch/MIPS/kernel/init_task.o
This makefile is included through include $ (srctree)/ARCH/$ (srcarch)/makefile.
Init-y is defined in makefile:
Init-Y: = init/
...
Init-Y: = $ (patsubst %/, %/built-in.o, $ (init-y ))
The final result is:
Init-Y: = init/built-in.o. This build-in.o this intermediate file may have heard of, in fact, this file is the directory under all obj-y to synthesize.
In addition, you can find the following two variables:
Vmlinux-Main :=$ (core-y) $ (libs-y) $ (drivers-y) $ (net-y)
Vmlinux-LDS: = ARCH/$ (ARCH)/kernel/vmlinux. LDS
Vmlinux-dirs
Pay attention to the following sentence:
$ (Sort $ (vmlinux-init) $ (vmlinux-Main) $ (vmlinux-LDS): $ (vmlinux-dirs );
This statement is generated by dependency before executing the vmlinux target. Let's take a look at the most critical vmlinux-dirs.
Vmlinux-dirs :=$ (patsubst %/, %, $ (filter %/, $ (init-y) $ (init-m )\
$ (Core-y) $ (core-m) $ (drivers-y) $ (drivers-m )\
$ (Net-y) $ (net-m) $ (libs-y) $ (libs-m )))
In fact, $ (vmlinux-dirs) is still a goal.
Phony + = $ (vmlinux-dirs)
$ (Vmlinux-dirs): prepare scripts
$ (Q) $ (make) $ (build) =$ @
Makefile. kbuild rules are used. The directory in vmlinux-dirs is recursively processed to generate those. O files, especially the build-in.o. When executing vmlinux, the $ (vmlinux-dirs) target will certainly be executed first.
Link to vmlinux
Where is the link? Let's see what follows endif:
$ (Call if_changed_rule, vmlinux __)
$ (Q) $ (make)-F $ (srctree)/scripts/makefile. modpost $ @
$ (Call if_changed_rule, vmlinux _) will call rule_vmlinux _, that is, the following content:
# Link of vmlinux
# If config_kallsyms is set. version is already updated
# Generate system. Map and verify that the content is consistent
# Use + In Front Of The vmlinux_version rule to silent warning with make-J2
# First Command is ':' to allow us to use + in front of the rule
Define rule_vmlinux __
:
$ (If $ (config_kallsyms), + $ (call cmd, vmlinux_version ))
$ (Call cmd, vmlinux __)
$ (Q) echo 'cmd _ $ @: = $ (cmd_vmlinux _) '> $ (@ d)/. $ (@ f). cmd
$ (Q) $ (if $ (quiet) pai_sysmap ),\
Echo '$ (quiet) cmd_sysmap) system. map '&&)\
$ (Pai_sysmap) $ @ system. Map ;\
If [$? -Ne 0]; then \
Rm-F $ @;\
/Bin/false ;\
FI;
$ (Verify_kallsyms)
Endef
The command vmlinux __, _ vmlinux_version and sysmap are defined here. The vmlinux _ command contains the LD link to generate vmlinux.
# Rule to link vmlinux-also used during config_kallsyms
# May be overridden by arch/$ (ARCH)/makefile
Quiet_cmd_vmlinux __? = LD $ @
Cmd_vmlinux __? = $ (LD) $ (ldflags) $ (ldflags_vmlinux)-o $ @\
-T $ (vmlinux-LDS) $ (vmlinux-init )\
-- Start-group $ (vmlinux-Main) -- end-group \
$ (Filter-out $ (vmlinux-LDS) $ (vmlinux-init) $ (vmlinux-Main) Force, $ ^)
# Generate new vmlinux version
Quiet_cmd_vmlinux_version = gen. Version
Pai_vmlinux_version = set-E ;\
If [! -R. Version]; then \
Rm-F. version ;\
Echo 1>. version ;\
Else \
MV. version. old_version ;\
Expr 0 $ (Cat. old_version) + 1>. version ;\
FI ;\
$ (Make) $ (build) = init
# Generate system. Map
Quiet_pai_sysmap = sysmap
Performance_sysmap = $ (config_shell) $ (srctree)/scripts/mksysmap
2. makefile. kbuild rules:
$ (Q) $ (make)-F $ (if $ (kbuild_src), $ (srctree)/) scripts/makefile. Build \
OBJ = $ (vmlinux-dirs)
Find the target _ build:
_ Build: $ (if $ (kbuild_builtin), $ (builtin-target) $ (Lib-target) $ (extra-y ))\
$ (If $ (kbuild_modules), $ (obj-m ))\
$ (Subdir-ym) $ (always)
@:
Because kbuild_builtin is initialized to 1 in the top-layer makefile, the dependency of this rule has a builtin-target variable:
Ifneq ($ (Strip $ (obj-y) $ (obj-m) $ (obj-N) $ (obj-) $ (Lib-target )),)
Builtin-target: = $ (OBJ)/built-in.o
Endif
The variable obj is the directory specified by the vmlinux-dirs variable. So here we will build $ (vmlinux-dirs)/built-in.o goals:
Ifdef builtin-Target
Quiet_cmd_link_o_target = LD $ @
# If the list of objects to link is empty, just create an empty built-in.o
Export _link_o_target =$ (if $ (Strip $ (obj-y )),\
$ (LD) $ (ld_flags)-R-o $ @ $ (filter $ (obj-y), $ ^ ),\
Rm-F $ @; $ (AR) RCS $ @)
The above is generated by. o specified by obj-y $ (vmlinux-dirs)/built-in.o.
$ (Builtin-target): $ (obj-y) Force
$ (Call if_changed, link_o_target)
The MAKEFILE file in the directory specified by the vmlinux-dirs variable is included below. In these makefile files, the obj-y variable is specified, which specifies some *. O target files,
Kbuild-Dir: = $ (if $ (filter/%, $ (SRC), $ (SRC), $ (srctree)/$ (SRC ))
Include $ (if $ (wildcard $ (kbuild-DIR)/kbuild), $ (kbuild-DIR)/kbuild, $ (kbuild-DIR)/makefile)
These *. o file generation methods are specified by the pattern rules of the scripts/makefile. Build File.
%. O: %. c force
$ (Call cmd, force_checksrc)
$ (Call if_changed_rule, cc_o_c)
The above will generate the. o specified by obj-y.
Through the above steps, the target specified by the vmlinux-init variable is compiled and linked. the build of the target specified by the vmlinux-main variable is similar to this.
Tianxingjian, a gentleman is always striving for self-improvement