当前位置: 首页 > news >正文

东道网站建设做阿里巴巴跟网站哪个更好

东道网站建设,做阿里巴巴跟网站哪个更好,家具网站案例,企业网站的开发公司目录前602行分析make xxx_defconfig 过程Makefile.build 脚本分析make 过程built-in.o 文件编译生成过程make zImage 过程前几章我们重点讲解了如何移植uboot 到I.MX6U-ALPHA 开发板上#xff0c;从本章开始我们就开始学习如何移植Linux 内核。同uboot 一样#xff0c;在具体… 目录前602行分析make xxx_defconfig 过程Makefile.build 脚本分析make 过程built-in.o 文件编译生成过程make zImage 过程前几章我们重点讲解了如何移植uboot 到I.MX6U-ALPHA 开发板上从本章开始我们就开始学习如何移植Linux 内核。同uboot 一样在具体移植之前我们先来学习一下Linux 内核的顶层Makefile 文件因为顶层Makefile 控制着Linux 内核的编译流程。 前602行分析 Linux 的顶层Makefile 和uboot 的顶层Makefile 非常相似因为uboot 参考了Linux前602行几乎一样所以前面部分我们大致看一下就行了。 1、版本号 顶层Makefile 一开始就是Linux 内核的版本号如下所示 1 VERSION 4 2 PATCHLEVEL 1 3 SUBLEVEL 15 4 EXTRAVERSION 可以看出Linux 内核版本号为4.1.15。 2、MAKEFLAGS 变量 MAKEFLAGS 变量设置如下所示 16 MAKEFLAGS -rR --include-dir$(CURDIR)3、命令输出 Linux 编译的时候也可以通过“V1”来输出完整的命令这个和uboot 一样相关代码如下所示 69 ifeq ($(origin V), command line) 70 KBUILD_VERBOSE $(V) 71 endif 72 ifndef KBUILD_VERBOSE 73 KBUILD_VERBOSE 0 74 endif 75 76 ifeq ($(KBUILD_VERBOSE),1) 77 quiet 78 Q 79 else 80 quietquiet_ 81 Q 82 endif4、静默输出 Linux 编译的时候使用“make -s”就可实现静默编译编译的时候就不会打印任何的信息同uboot 一样相关代码如下 87 ifneq ($(filter 4.%,$(MAKE_VERSION)),) # make-4 88 ifneq ($(filter %s ,$(firstword x$(MAKEFLAGS))),) 89 quietsilent_ 90 endif 91 else # make-3.8x 92 ifneq ($(filter s% -s%,$(MAKEFLAGS)),) 93 quietsilent_ 94 endif 95 endif 96 97 export quiet Q KBUILD_VERBOSE5、设置编译结果输出目录 Linux 编译的时候使用“Oxxx”即可将编译产生的过程文件输出到指定的目录中相关代码如下 116 ifeq ($(KBUILD_SRC),) 117 118 # OK, Make called in directory where kernel src resides 119 # Do we want to locate output files in a separate directory? 120 ifeq ($(origin O), command line) 121 KBUILD_OUTPUT : $(O) 122 endif6、代码检查 Linux 也支持代码检查使用命令“make C1”使能代码检查检查那些需要重新编译的文件。“make C2”用于检查所有的源码文件顶层Makefile 中的代码如下 172 ifeq ($(origin C), command line) 173 KBUILD_CHECKSRC $(C) 174 endif 175 ifndef KBUILD_CHECKSRC 176 KBUILD_CHECKSRC 0 177 endif7、模块编译 Linux 允许单独编译某个模块使用命令“make Mdir”即可旧语法“make SUBDIRSdir”也是支持的。顶层Makefile 中的代码如下 179 # Use make Mdir to specify directory of external module to build 180 # Old syntax make ... SUBDIRS$PWD is still supported 181 # Setting the environment variable KBUILD_EXTMOD take precedence 182 ifdef SUBDIRS 183 KBUILD_EXTMOD ? $(SUBDIRS) 184 endif 185 186 ifeq ($(origin M), command line) 187 KBUILD_EXTMOD : $(M) 188 endif 189 190 # If building an external module we do not care about the all: rule 191 # but instead _all depend on modules 192 PHONY all 193 ifeq ($(KBUILD_EXTMOD),) 194 _all: all 195 else 196 _all: modules 197 endif 198 199 ifeq ($(KBUILD_SRC),) 200 # building in the source tree 201 srctree : . 202 else 203 ifeq ($(KBUILD_SRC)/,$(dir $(CURDIR))) 204 # building in a subdirectory of the source tree 205 srctree : .. 206 else 207 srctree : $(KBUILD_SRC) 208 endif 209 endif 210 objtree : . 211 src : $(srctree) 212 obj : $(objtree) 213 214 VPATH : $(srctree)$(if $(KBUILD_EXTMOD),:$(KBUILD_EXTMOD)) 215 216 export srctree objtree VPATH外部模块编译过程和uboot 也一样最终导出srctree、objtree 和VPATH 这三个变量的值其中srctree.也就是当前目录objtree 同样为“.”。 8、设置目标架构和交叉编译器 同uboot 一样Linux 编译的时候需要设置目标板架构ARCH 和交叉编译器CROSS_COMPILE在顶层Makefile 中代码如下 252 ARCH ? $(SUBARCH) 253 CROSS_COMPILE ? $(CONFIG_CROSS_COMPILE:%%)为了方便一般直接修改顶层Makefile 中的ARCH 和CROSS_COMPILE直接将其设置为对应的架构和编译器比如本教程将ARCH 设置为为armCROSS_COMPILE 设置为arm-linux-gnueabihf-如下所示 252 ARCH ? arm 253 CROSS_COMPILE ? arm-linux-gnueabihf-设置好以后我们就可以使用如下命令编译Linux 了 make xxx_defconfig //使用默认配置文件配置Linux make menuconfig //启动图形化配置界面 make -j16 //编译Linux9、调用scripts/Kbuild.include 文件 同uboot 一样Linux 顶层Makefile 也会调用文件scripts/Kbuild.include顶层Makefile 相应代码如下 348 # We need some generic definitions (do not try to remake the file). 349 scripts/Kbuild.include: ; 350 include scripts/Kbuild.include10、交叉编译工具变量设置 顶层Makefile 中其他和交叉编译器有关的变量设置如下 353 AS $(CROSS_COMPILE)as 354 LD $(CROSS_COMPILE)ld 355 CC $(CROSS_COMPILE)gcc 356 CPP $(CC) -E 357 AR $(CROSS_COMPILE)ar 358 NM $(CROSS_COMPILE)nm 359 STRIP $(CROSS_COMPILE)strip 360 OBJCOPY $(CROSS_COMPILE)objcopy 361 OBJDUMP $(CROSS_COMPILE)objdump LA、LD、CC 等这些都是交叉编译器所使用的工具。 11、头文件路径变量 顶层Makefile 定义了两个变量保存头文件路径USERINCLUDE 和LINUXINCLUDE相关代码如下 381 USERINCLUDE : \ 382 -I$(srctree)/arch/$(hdr-arch)/include/uapi \ 383 -Iarch/$(hdr-arch)/include/generated/uapi \ 384 -I$(srctree)/include/uapi \ 385 -Iinclude/generated/uapi \ 386 -include $(srctree)/include/linux/kconfig.h 387 388 # Use LINUXINCLUDE when you must reference the include/ directory. 389 # Needed to be compatible with the O option 390 LINUXINCLUDE : \ 391 -I$(srctree)/arch/$(hdr-arch)/include \ 392 -Iarch/$(hdr-arch)/include/generated/uapi \ 393 -Iarch/$(hdr-arch)/include/generated \ 394 $(if $(KBUILD_SRC), -I$(srctree)/include) \ 395 -Iinclude \ 396 $(USERINCLUDE)第381~386 行是USERINCLUDE 是UAPI 相关的头文件路径第390~396 行是LINUXINCLUDE 是Linux 内核源码的头文件路径。重点来看一下LINUXINCLUDE其中 srctree.hdr-archarmKBUILD_SRC 为空因此将USERINCLUDE 和LINUXINCLUDE 展开以后为 USERINCLUDE : \ -I./arch/arm/include/uapi \ -Iarch/arm/include/generated/uapi \ -I./include/uapi \ -Iinclude/generated/uapi \ -include ./include/linux/kconfig.h LINUXINCLUDE : \ -I./arch/arm/include \ -Iarch/arm/include/generated/uapi \ -Iarch/arm/include/generated \ -Iinclude \ -I./arch/arm/include/uapi \ -Iarch/arm/include/generated/uapi \ -I./include/uapi \ -Iinclude/generated/uapi \ -include ./include/linux/kconfig.h12、导出变量 顶层Makefile 会导出很多变量给子Makefile 使用导出的这些变量如下 417 export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION 418 export ARCH SRCARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC 419 export CPP AR NM STRIP OBJCOPY OBJDUMP 420 export MAKE AWK GENKSYMS INSTALLKERNEL PERL PYTHON UTS_MACHINE 421 export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS 422 423 export KBUILD_CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS 424 export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE CFLAGS_GCOV CFLAGS_KASAN 425 export KBUILD_AFLAGS AFLAGS_KERNEL AFLAGS_MODULE 426 export KBUILD_AFLAGS_MODULE KBUILD_CFLAGS_MODULE KBUILD_LDFLAGS_MODULE 427 export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL 428 export KBUILD_ARFLAGSmake xxx_defconfig 过程 第一次编译Linux 之前都要使用“make xxx_defconfig”先配置Linux 内核在顶层Makefile中有“%config”这个目标如下所示 490 config-targets : 0 491 mixed-targets : 0 492 dot-config : 1 493 494 ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),) 495 ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),) 496 dot-config : 0 497 endif 498 endif 499 500 ifeq ($(KBUILD_EXTMOD),) 501 ifneq ($(filter config %config,$(MAKECMDGOALS)),) 502 config-targets : 1 503 ifneq ($(words $(MAKECMDGOALS)),1) 504 mixed-targets : 1 505 endif 506 endif 507 endif 508 509 ifeq ($(mixed-targets),1) 510 # 511 # Were called with mixed targets (*config and build targets). 512 # Handle them one by one. 513 514 PHONY $(MAKECMDGOALS) __build_one_by_one 515 516 $(filter-out __build_one_by_one, $(MAKECMDGOALS)): __build_one_by_one 517 : 518 519 __build_one_by_one: 520 $(Q)set -e; \ 521 for i in $(MAKECMDGOALS); do \ 522 $(MAKE) -f $(srctree)/Makefile $$i; \ 523 done 524 525 else 526 ifeq ($(config-targets),1) 527 # 528 # *config targets only - make sure prerequisites are updated, and 529 # descend in scripts/kconfig to make the *config target 530 531 # Read arch specific Makefile to set KBUILD_DEFCONFIG as needed. 532 # KBUILD_DEFCONFIG may point out an alternative default 533 # configuration used for make defconfig 534 include arch/$(SRCARCH)/Makefile 535 export KBUILD_DEFCONFIG KBUILD_KCONFIG 536 537 config: scripts_basic outputmakefile FORCE 538 $(Q)$(MAKE) $(build)scripts/kconfig $ 539 540 %config: scripts_basic outputmakefile FORCE 541 $(Q)$(MAKE) $(build)scripts/kconfig $ 542 543 else 563 endif # KBUILD_EXTMOD ...... 第490~507 行和uboot 一样都是设置定义变量config-targets、mixed-targets 和dot-config 的值最终这三个变量的值为 config-targets 1 mixed-targets 0 dot-config 1因为config-targets1因此第534 行~541 行成立。第534 行引用arch/arm/Makefile 这个文件这个文件很重要因为zImage、uImage 等这些文件就是由arch/arm/Makefile 来生成的。 第535 行导出变量KBUILD_DEFCONFIG KBUILD_KCONFIG。 第537 行没有目标与之匹配因此不执行。 第540 行“make xxx_defconfig”与目标“%config”匹配因此执行。“%config”依赖scripts_basic、outputmakefile 和FORCE“%config”真正有意义的依赖就只有scripts_basicscripts_basic 的规则如下 448 scripts_basic: 449 $(Q)$(MAKE) $(build)scripts/basic 450 $(Q)rm -f .tmp_quiet_recordmcountbuild 定义在文件scripts/Kbuild.include 中值为build : -f $(srctree)/scripts/Makefile.build obj因此将示例代码35.5.1.2 展开就是 scripts_basic: make -f ./scripts/Makefile.build objscripts/basic //也可以没有视配置而定 rm -f . tmp_quiet_recordmcount //也可以没有 接着回到示例代码35.5.1.1 的目标“%config”处内容如下 %config: scripts_basic outputmakefile FORCE$(Q)$(MAKE) $(build)scripts/kconfig $将命令展开就是 make -f ./scripts/Makefile.build objscripts/kconfig xxx_defconfigMakefile.build 脚本分析 从上一小节可知“make xxx_defconfig“配置Linux 的时候如下两行命令会执行脚本 scripts/Makefile.build make -f ./scripts/Makefile.build objscripts/basic make -f ./scripts/Makefile.build objscripts/kconfig xxx_defconfig我们依次来分析一下 1、scripts_basic 目标对应的命令 scripts_basic 目标对应的命令为make -f ./scripts/Makefile.build objscripts/basic。打开文件scripts/Makefile.build有如下代码 41 # The filename Kbuild has precedence over Makefile 42 kbuild-dir : $(if $(filter /%,$(src)),$(src),$(srctree)/$(src)) 43 kbuild-file : $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile) 44 include $(kbuild-file)将kbuild-dir 展开后为 kbuild-dir./scripts/basic将kbuild-file 展开后为 kbuild-file ./scripts/basic/Makefile最后将59 行展开即 include ./scripts/basic/Makefile继续分析scripts/Makefile.build如下代码 94 __build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \ 95 $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \ 96 $(subdir-ym) $(always) 97 :__build 是默认目标因为命令“make -f ./scripts/Makefile.build objscripts/basic”没有指 定目标所以会使用到默认目标__build。在顶层Makefile 中KBUILD_BUILTIN 为1 KBUILD_MODULES 为空因此展开后目标__build 为 __build:$(builtin-target) $(lib-target) $(extra-y)) $(subdir-ym) $(always) :可以看出目标__build 有5 个依赖builtin-target、lib-target、extra-y、subdir-ym 和always。 这5 个依赖的具体内容如下 builtin-target lib-target extra-y subdir-ym always scripts/basic/fixdep scripts/basic/bin2c只有always 有效因此__build 最终为 __build: scripts/basic/fixdep scripts/basic/bin2c :__build 依赖于scripts/basic/fixdep 和scripts/basic/bin2c所以要先将scripts/basic/fixdep 和scripts/basic/bin2c.c 这两个文件编译成fixdep 和bin2c。 综上所述scripts_basic 目标的作用就是编译出scripts/basic/fixdep 和scripts/basic/bin2c 这两个软件。 2、%config 目标对应的命令 %config 目标对应的命令为make -f ./scripts/Makefile.build objscripts/kconfig xxx_defconfig此命令会使用到的各个变量值如下 src scripts/kconfig kbuild-dir ./scripts/kconfig kbuild-file ./scripts/kconfig/Makefile include ./scripts/kconfig/Makefile可以看出Makefile.build 会读取scripts/kconfig/Makefile 中的内容此文件有如下所示内容 113 %_defconfig: $(obj)/conf 114 $(Q)$ $(silent) --defconfigarch/$(SRCARCH)/configs/$ $(Kconfig)目标%_defconfig 与xxx_defconfig 匹配所以会执行这条规则将其展开就是 %_defconfig: scripts/kconfig/confscripts/kconfig/conf --defconfigarch/arm/configs/%_defconfig Kconfig%_defconfig 依赖scripts/kconfig/conf所以会编译scripts/kconfig/conf.c 生成conf 这个软件。此软件就会将%_defconfig 中的配置输出到.config 文件中最终生成Linux kernel 根目录下的.config 文件。 make 过程 使用命令“make xxx_defconfig”配置好Linux 内核以后就可以使用“make”或者“make all”命令进行编译。顶层Makefile 有如下代码 125 PHONY : _all 126 _all: ...... 192 PHONY all 193 ifeq ($(KBUILD_EXTMOD),) 194 _all: all 195 else 196 _all: modules 197 endif ...... 608 all: vmlinux第126 行_all 是默认目标如果使用命令“make”编译Linux 的话此目标就会被匹配。 第193 行如果KBUILD_EXTMOD 为空的话194 行的代码成立。 第194 行默认目标_all 依赖all。 第608 行目标all 依赖vmlinux所以接下来的重点就是vmlinux 顶层Makefile 中有如下代码 904 # Externally visible symbols (used by link-vmlinux.sh) 905 export KBUILD_VMLINUX_INIT : $(head-y) $(init-y) 906 export KBUILD_VMLINUX_MAIN : $(core-y) $(libs-y) $(drivers-y) $(net-y) 907 export KBUILD_LDS : arch/$(SRCARCH)/kernel/vmlinux.lds 908 export LDFLAGS_vmlinux 909 # used by scripts/pacmage/Makefile 910 export KBUILD_ALLDIRS : $(sort $(filter-out arch/%,$(vmlinux-alldirs)) arch Documentation include samples scripts tools virt) 911 912 vmlinux-deps : $(KBUILD_LDS) $(KBUILD_VMLINUX_INIT) $(KBUILD_VMLINUX_MAIN) 913 914 # Final link of vmlinux 915 cmd_link-vmlinux $(CONFIG_SHELL) $ $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) 916 quiet_cmd_link-vmlinux LINK $ 917 918 # Include targets which we want to 919 # execute if the rest of the kernel build went well. 920 vmlinux: scripts/link-vmlinux.sh $(vmlinux-deps) FORCE 921 ifdef CONFIG_HEADERS_CHECK 922 $(Q)$(MAKE) -f $(srctree)/Makefile headers_check 923 endif 924 ifdef CONFIG_SAMPLES 925 $(Q)$(MAKE) $(build)samples 926 endif 927 ifdef CONFIG_BUILD_DOCSRC 928 $(Q)$(MAKE) $(build)Documentation 929 endif 930 ifdef CONFIG_GDB_SCRIPTS 931 $(Q)ln -fsn cd $(srctree) /bin/pwd/scripts/gdb/vmlinux-gdb.py 932 endif 933 $(call if_changed,link-vmlinux)从第920 行可以看出目标vmlinux 依赖scripts/link-vmlinux.sh $(vmlinux-deps) FORCE。第912 行定义了vmlinux-deps值为 vmlinux-deps $(KBUILD_LDS) $(KBUILD_VMLINUX_INIT) $(KBUILD_VMLINUX_MAIN) 第905 行KBUILD_VMLINUX_INIT $(head-y) $(init-y)。 第906 行KBUILD_VMLINUX_MAIN $(core-y) $(libs-y) $(drivers-y) $(net-y)。 第907 行KBUILD_LDS arch/ $ (SRCARCH)/kernel/vmlinux.lds其中SRCARCHarm因此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。 第933 行的命令用于链接生成vmlinux。 重点来看一下$ (head-y) 、$ (init-y)、$ (core-y) 、$ (libs-y) 、$ (drivers-y) 和$ (net-y)这六个变量的值。 1、head-y head-y 定义在文件arch/arm/Makefile 中内容如下 135 head-y : arch/arm/kernel/head$(MMUEXT).o当不使能MMU 的话MMUEXT-nommu如果使能MMU 的话为空因此head-y 最终的值为 head-y arch/arm/kernel/head.o2、init-y、drivers-y 和net-y 在顶层Makefile 中有如下代码 558 init-y : init/ 559 drivers-y : drivers/ sound/ firmware/ 560 net-y : net/ ...... 896 init-y : $(patsubst %/, %/built-in.o, $(init-y)) 898 drivers-y : $(patsubst %/, %/built-in.o, $(drivers-y)) 899 net-y : $(patsubst %/, %/built-in.o, $(net-y))从示例代码35.5.3.4 可知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.o3、libs-y libs-y 基本和init-y 一样在顶层Makefile 中存在如下代码 561 libs-y : lib/ ...... 900 libs-y1 : $(patsubst %/, %/lib.a, $(libs-y)) 901 libs-y2 : $(patsubst %/, %/built-in.o, $(libs-y)) 902 libs-y : $(libs-y1) $(libs-y2)根据示例代码35.5.3.5 可知libs-y 应该等于“lib.a built-in.o”这个只正确了一部分因为 在arch/arm/Makefile 中会向libs-y 中追加一些值代码如下 286 libs-y : arch/arm/lib/ $(libs-y)arch/arm/Makefile 将libs-y 的值改为了arch/arm/lib $(libs-y)展开以后为 libs-y arch/arm/lib lib/因此根据示例代码35.5.3.5 的第900~902 行可知libs-y 最终应该为 libs-y arch/arm/lib/lib.a lib/lib.a arch/arm/lib/built-in.o lib/built-in.o4、core-y core-y 和init-y 也一样在顶层Makefile 中有如下代码 532 core-y : usr/ ...... 887 core-y kernel/ mm/ fs/ ipc/ security/ crypto/ block/但是在arch/arm/Makefile 中会对core-y 进行追加代码如下 269 core-$(CONFIG_FPE_NWFPE) arch/arm/nwfpe/ 270 core-$(CONFIG_FPE_FASTFPE) $(FASTFPE_OBJ) 271 core-$(CONFIG_VFP) arch/arm/vfp/ 272 core-$(CONFIG_XEN) arch/arm/xen/ 273 core-$(CONFIG_KVM_ARM_HOST) arch/arm/kvm/ 274 core-$(CONFIG_VDSO) arch/arm/vdso/ 275 276 # If we have a machine-specific directory, then include it in the build. 277 core-y arch/arm/kernel/ arch/arm/mm/ arch/arm/common/ 278 core-y arch/arm/probes/ 279 core-y arch/arm/net/ 280 core-y arch/arm/crypto/ 281 core-y arch/arm/firmware/ 282 core-y $(machdirs) $(platdirs)第269~274 行根据不同的配置向core-y 追加不同的值比如使能VFP 的话就会在.config中有CONFIG_VFPy 这一行那么core-y 就会追加“arch/arm/vfp/”。 第277~282 行就是对core-y 直接追加的值。 在顶层Makefile 中有如下一行 897 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关于head-y 、init-y、core-y 、libs-y 、drivers-y 和net-y 这6 个变量就讲解到这里。这些变量都是一些built-in.o 或.a 等文件这个和uboot 一样都是将相应目录中的源码文件进行编译然后在各自目录下生成built-in.o 文件有些生成了.a 库文件。最终将这些built-in.o 和.a 文件进行链接即可形成ELF 格式的可执行文件也就是vmlinux但是链接是需要链接脚本的vmlinux 的依赖arch/arm/kernel/vmlinux.lds 就是整个Linux 的链接脚本。 示例代码35.5.3.2 第933 行的命令“(callifchanged,link−vmlinux)”表示将(call if_changed,link-vmlinux) ”表示将(callifc​hanged,link−vmlinux)”表示将(call if_changed,link-vmlinux)的结果作为最终生成vmlinux 的命令前面的“”表示该命令结果不可忽略。$(call if_changed,link-vmlinux)是调用函数if_changedlink-vmlinux 是函数if_changed 的参数函数if_changed 定义在文件scripts/Kbuild.include 中如下所示 247 if_changed $(if $(strip $(any-prereq) $(arg-check)), \ 248 set -e; \ 249 $(echo-cmd) $(cmd_$(1)); \ 250 printf %s\n cmd_$ : $(make-cmd) $(dot-target).cmd)any-prereq 用于检查依赖文件是否有变化如果依赖文件有变化那么any-prereq 就不为空否则就为空。arg-check 用于检查参数是否有变化如果没有变化那么arg-check 就为空。 第248 行“set -e”告诉bash如果任何语句的执行结果不为true(也就是执行出错)的话就直接退出。 第249 行$ (echo-cmd)用于打印命令执行过程比如在链接vmlinux 的时候就会输出“LINK vmlinux”。$ (cmd_$ (1))中的$ (1)表示参数也就是link-vmlinux因此$ (cmd_$(1))表示执行cmd_link-vmlinux 的内容。cmd_link-vmlinux 在顶层Makefile 中有如下所示定义 914 # Final link of vmlinux 915 cmd_link-vmlinux $(CONFIG_SHELL) $ $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) 916 quiet_cmd_link-vmlinux LINK $第915 行就是cmd_link-vmlinux 的值其中CONFIG_SHELL/bin/bash$表示目标vmlinux的第一个依赖文件根据示例代码35.5.3.2 可知这个文件为scripts/link-vmlinux.sh。LD arm-linux-gnueabihf-ld -ELLDFLAGS 为空。LDFLAGS_vmlinux 的值由顶层Makefile 和arch/arm/Makefile 这两个文件共同决定最终LDFLAGS_vmlinux-p --no-undefined -X --pic-veneer --build-id。因此cmd_link-vmlinux 最终的值为 cmd_link-vmlinux /bin/bash scripts/link-vmlinux.sh arm-linux-gnueabihf-ld -EL -p --no-undefined -X --pic-veneer --build-idcmd_link-vmlinux 会调用scripts/link-vmlinux.sh 这个脚本来链接出vmlinux在link-vmlinux.sh 中有如下所示代码 51 vmlinux_link() 52 { 53 local lds${objtree}/${KBUILD_LDS} 54 55 if [ ${SRCARCH} ! um ]; then 56 ${LD} ${LDFLAGS} ${LDFLAGS_vmlinux} -o ${2} \ 57 -T ${lds} ${KBUILD_VMLINUX_INIT} \ 58 --start-group ${KBUILD_VMLINUX_MAIN} --end-group ${1} 59 else 60 ${CC} ${CFLAGS_vmlinux} -o ${2} \ 61 -Wl,-T,${lds} ${KBUILD_VMLINUX_INIT} \ 62 -Wl,--start-group \ 63 ${KBUILD_VMLINUX_MAIN} \ 64 -Wl,--end-group \ 65 -lutil ${1} 66 rm -f linux 67 fi 68 } ...... 216 info LD vmlinux 217 vmlinux_link ${kallsymso} vmlinuxvmliux_link 就是最终链接出vmlinux 的函数第55 行判断SRCARCH 是否等于“um”如果不相等的话就执行56~58 行的代码。因为SRCARCHarm因此条件成立执行56~58 行的代码。这三行代码就应该很熟悉了就是普通的链接操作连接脚本为lds ./arch/arm/kernel/vmlinux.lds 需要链接的文件由变量KBUILD_VMLINUX_INIT 和KBUILD_VMLINUX_MAIN 来决定这两个变量在示例代码35.5.3.2 中已经讲解过了。 第217 行调用vmlinux_link 函数来链接出vmlinux。 使用命令“make V1”编译Linux会有如图35.5.3.1 所示的编译信息 至此我们基本理清了make 的过程重点就是将各个子目录下的built-in.o、.a 等文件链接在一起最终生成vmlinux 这个ELF 格式的可执行文件。链接脚本为arch/arm/kernel/vmlinux.lds链接过程是由shell 脚本scripts/link-vmlinux.s 来完成的。接下来的问题就是这些子目录下的built-in.o、.a 等文件又是如何编译出来的呢 built-in.o 文件编译生成过程 根据示例代码35.5.3.2 第920 行可知vmliux 依赖vmlinux-deps而vmlinux-deps $(KBUILD_LDS) $(KBUILD_VMLINUX_INIT) $(KBUILD_VMLINUX_MAIN)KBUILD_LDS是链接脚本这里不考虑剩下的KBUILD_VMLINUX_INIT 和KBUILD_VMLINUX_MAIN 就是各个子目录下的built-in.o、.a 等文件。最终vmlinux-deps 的值如下 除了arch/arm/kernel/vmlinux.lds 以外其他都是要编译链接生成的。在顶层Makefile 中有如下代码 937 $(sort $(vmlinux-deps)): $(vmlinux-dirs) ;sort 是排序函数用于对vmlinux-deps 的字符串列表进行排序并且去掉重复的单词。可以看出vmlinux-deps 依赖vmlinux-dirsvmlinux-dirs 也定义在顶层Makefile 中定义如下 889 vmlinux-dirs : $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \ 890 $(core-y) $(core-m) $(drivers-y) $(drivers-m) \ 891 $(net-y) $(net-m) $(libs-y) $(libs-m))) vmlinux-dirs 看名字就知道和目录有关此变量保存着生成vmlinux 所需源码文件的目录值如下 在顶层Makefile 中有如下代码 946 $(vmlinux-dirs): prepare scripts 947 $(Q)$(MAKE) $(build)$目标vmlinux-dirs 依赖prepare 和scripts这两个依赖不去浪费时间了重点看一下第947行的命令。build 前面已经说了值为“-f ./scripts/Makefile.build obj”因此将947 行的命令展开就是 make -f ./scripts/Makefile.build obj$$表示目标文件也就是vmlinux-dirs 的值将vmlinux-dirs 中的这些目录全部带入到命令中结果如下 make -f ./scripts/Makefile.build objinitmake -f ./scripts/Makefile.build objusrmake -f ./scripts/Makefile.build objarch/arm/vfpmake -f ./scripts/Makefile.build objarch/arm/vdsomake -f ./scripts/Makefile.build objarch/arm/kernelmake -f ./scripts/Makefile.build objarch/arm/mmmake -f ./scripts/Makefile.build objarch/arm/commonmake -f ./scripts/Makefile.build objarch/arm/probesmake -f ./scripts/Makefile.build objarch/arm/netmake -f ./scripts/Makefile.build objarch/arm/cryptomake -f ./scripts/Makefile.build objarch/arm/firmwaremake -f ./scripts/Makefile.build objarch/arm/mach-imxmake -f ./scripts/Makefile.build objkernelmake -f ./scripts/Makefile.build objmmmake -f ./scripts/Makefile.build objfsmake -f ./scripts/Makefile.build objipcmake -f ./scripts/Makefile.build objsecuritymake -f ./scripts/Makefile.build objcryptomake -f ./scripts/Makefile.build objblockmake -f ./scripts/Makefile.build objdriversmake -f ./scripts/Makefile.build objsoundmake -f ./scripts/Makefile.build objfirmwaremake -f ./scripts/Makefile.build objnetmake -f ./scripts/Makefile.build objarch/arm/libmake -f ./scripts/Makefile.build objlib 这些命令运行过程其实都是一样的我们就以“ make -f ./scripts/Makefile.build objinit”这个命令为例讲解一下详细的运行过程。这里又要用到Makefile.build 这个脚本了此脚本默认目标为__build这个在35.5.2 小节已经讲过了我们再来看一下__build 目标对应的规则如下 94 __build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \ 95 $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \ 96 $(subdir-ym) $(always) 97 : 当只编译Linux 内核镜像文件也就是使用“make zImage ”编译的时候 KBUILD_BUILTIN1KBUILD_MODULES 为空。“make”命令是会编译所有的东西包括Linux内核镜像文件和一些模块文件。如果只编译Linux 内核镜像的话__build 目标简化为 __build: $(builtin-target) $(lib-target) $(extra-y)) $(subdir-ym) $(always) :重点来看一下builtin-target 这个依赖builtin-target 同样定义在文件scripts/Makefile.build中定义如下 86 ifneq ($(strip $(obj-y) $(obj-m) $(obj-) $(subdir-m) $(lib-target)),) 87 builtin-target : $(obj)/built-in.o 88 endif第87 行就是builtin-target 变量的值为“$(obj)/built-in.o”这就是这些built-in.o 的来源了。 要生成built-in.o要求obj-y、obj-m、obj-、subdir-m 和lib-target 这些变量不能全部为空。最后一个问题built-in.o 是怎么生成的在文件scripts/Makefile.build 中有如下代码 325 # 326 # Rule to compile a set of .o files into one .o file 327 # 328 ifdef builtin-target 329 quiet_cmd_link_o_target LD $ 330 # If the list of objects to link is empty, just create an empty built-in.o 331 cmd_link_o_target $(if $(strip $(obj-y)),\ 332 $(LD) $(ld_flags) -r -o $ $(filter $(obj-y), $^) \ 333 $(cmd_secanalysis),\ 334 rm -f $; $(AR) rcs$(KBUILD_ARFLAGS) $) 335 336 $(builtin-target): $(obj-y) FORCE 337 $(call if_changed,link_o_target) 338 339 targets $(builtin-target) 340 endif # builtin-target 第336 行的目标就是builtin-target依赖为obj-y命令为“KaTeX parse error: Double subscript at position 24: …_changed,link_o_̲target)”也就是调用函…(1)所对应的命令($(1)就是函数的第1 个参数)在这里就是调用 cmd_link_o_target 所对应的命令也就是第331~334 行的命令。cmd_link_o_target 就是使用LD将某个目录下的所有.o 文件链接在一起最终形成built-in.o。 make zImage 过程 1、vmlinux、ImagezImage、uImage 的区别 前面几小节重点是讲vmlinux 是如何编译出来的vmlinux 是ELF 格式的文件但是在实际中我们不会使用vmlinux而是使用zImage 或uImage 这样的Linux 内核镜像文件。那么vmlinux、zImage、uImage 他们之间有什么区别呢 ①、vmlinux 是编译出来的最原始的内核文件是未压缩的比如正点原子提供的Linux 源码编译出来的vmlinux 差不多有16MB如图35.5.5.1 所示 ②、Image 是Linux 内核镜像文件但是Image 仅包含可执行的二进制数据。Image 就是使用objcopy 取消掉vmlinux 中的一些其他信息比如符号表什么的。但是Image 是没有压缩过的Image 保存在arch/arm/boot 目录下其大小大概在12MB 左右如图35.5.5.2 所示 相比vmlinux 的16MBImage 缩小到了12MB。 ③、zImage 是经过gzip 压缩后的Image经过压缩以后其大小大概在6MB 左右如图35.5.5.3 所示 ④、uImage 是老版本uboot 专用的镜像文件uImag 是在zImage 前面加了一个长度为64字节的“头”这个头信息描述了该镜像文件的类型、加载位置、生成时间、大小等信息。但是新的uboot 已经支持了zImage 启动所以已经很少用到uImage 了除非你用的很古老的uboot。 使用“make”、“make all”、“make zImage”这些命令就可以编译出zImage 镜像在arch/arm/Makefile 中有如下代码 310 BOOT_TARGETS zImage Image xipImage bootpImage uImage ...... 315 $(BOOT_TARGETS): vmlinux 316 $(Q)$(MAKE) $(build)$(boot) MACHINE$(MACHINE) $(boot)/$ 第310 行变量BOOT_TARGETS 包含zImageImagexipImage 等镜像文件。 第315 行BOOT_TARGETS 依赖vmlinux因此如果使用“make zImage”编译的Linux 内 核的话首先肯定要先编译出vmlinux。 第316 行具体的命令比如要编译zImage那么命令展开以后如下所示 make -f ./scripts/Makefile.build objarch/arm/boot MACHINEarch/arm/boot/zImage看来又是使用scripts/Makefile.build 文件来完成vmlinux 到zImage 的转换。 关于Linux 顶层Makefile 就讲解到这里基本和uboot 的顶层Makefile 一样重点在于vmlinux 的生成。最后将vmlinux 压缩成我们最常用的zImage 或uImage 等文件。
http://www.pierceye.com/news/411309/

相关文章:

  • 常州网站制作报价wordpress 主页不显示图片
  • 如何在淘宝上做自己的网站东莞通网上营业厅
  • 北京专业响应式网站建设龙岗品牌网站建设
  • 网站qq联系怎么做莲都区建设分局网站
  • 河南旅游集团 网站建设网络运营与推广
  • 搭建网站要多少钱龙岩融胤网络科技有限公司
  • 网站建设实训报告命名规范深圳外贸网站开发
  • 深圳好看的公司网站做网站 网络科技公司
  • wordpress可以建哪些网站吗网站建设从哪入手
  • 网站建设合同下载建站工具包
  • 阜宁网站建设服务商江苏网络公司网站建设
  • 网站语言切换功能如何做wordpress 茶业 主题
  • 南昌企业网站模板建站济南好的seo
  • 食品建设网站公司简介模板免费下载
  • 重庆网站推广运营公司非常酷的wordpress主题
  • 网站未备案被阻断怎么做中国大数据公司排名10强
  • 柳市网站优化茶叶怎么做网站销售
  • 燕郊网站建设公司什么叫动漫设计与制作
  • 瑞安做网站的公司专门做2次元图片的网站
  • 为什么自己做的网站老是404错误个人建设网站流程
  • 柳州网站建设找哪家好沈阳线上教学
  • 外贸网站免费建设做暖暖视频网站大全
  • 做机票在线预订网站手机版传奇发布网站
  • 网站建设 深圳 凡科站内推广
  • 南宁做网站外包公众号二次开发
  • 中国做网站最好的公司郑州网站建设目标
  • 各大网站平台发布信息企业官网模板免费源码
  • 第一次做网站怎么样下手威联通如何做网站
  • 网站有哪几种类型郑州建设信息网可以领证书吗
  • wordpress 百度网盘网站semseo先做哪个