文章目录
- 0001-0008
- 0009-0018
- 0019-0051
- 0052-0092
- 0093-0107
- 0108-0123
- 0124-0177
- 0178-2315
- 0178-0181
- 0182-0186
- 0187-0202
- 0203-0245
- 0246-0262
- 0263-0272
- 0273-0337
- 0338-0383
- 0384-0387
- 0388-0425
- 0426-0449
- 0450-0474
- 0475-0486
- 0487-0498
- 0499-0534
- 0535-0550
- 0551-0565
- 0566-2218
- 2219
- 2220-2332
- 2233-2351
- 2252-2280
- 2281-2314
- 2315
- 2316-2323
uboot顶层Makefile分析1.png
提取码: w56a
uboot顶层Makefile分析2.png
提取码: ge29
0001-0008
版本号信息
0009-0018
MAKEFLAGS 变量
make 是支持递归调用的,也就是在 Makefile 中使用“make”命令来执行其他的 Makefile 文件,一般都是子目录中的 Makefile 文件。假如在当前目录下存在一个“subdir”子目录,这个子目录中又有其对应的 Makefile 文件,那么这个工程在编译的时候其主目录中的 Makefile 就可以调用子目录中的 Makefile,以此来完成所有子目录的编译。主目录的 Makefile 可以使用如下代码来编译这个子目录: $(MAKE) -C subdir
$(MAKE)
就是调用“make”命令,-C
指定子目录。有时候我们需要向子 make 传递变量,这个时候使用“export”来导出要传递给子 make 的变量即可,如果不希望哪个变量传递给子 make 的话就使用“unexport”来声明不导出。
0019-0051
1. 引用 include/host_arch.h
1. 查询平台
2. 导出变量
0052-0092
说明注释
0093-0107
命令输出(make V=number)
uboot 默认编译是不会在终端中显示完整的命令,都是短命令,在终端中输出短命令虽然看起来很清爽,但是不利于分析 uboot 的编译过程。可以通过设置变量“V=1“来实现完整的命令输出,这个在调试 uboot 的时候很有用。
$(origin <variable>)
作用:
它不操作变量的值,用于告诉你变量是哪来的。
参数:
variable 是变量名。
返回值:
变量来源。如果变量 V 是在命令行定义的那么它的来源就是"command line"。
0108-0123
静默输出(make -s)
设置 V=0 或者在命令行中不定义 V 的话,编译 uboot 的时候终端中显示的短命令,但是还是会有命令输出,有时候我们在编译 uboot 的时候不需要输出命令,这个时候就可以使用 uboot 的静默输出功能。编译的时候使用“make -s”即可实现静默输出。
$(filter <pattern…>,<text>)
作用:
过滤函数,以 pattern 模式过滤 text 字符串中的单词,仅保留符合模式 pattern 的单词,可以有多个模式。
返回值:
符合 pattern 的字符串。$(firstword <text>)
作用:
用于取出 text 字符串中的第一个单词。
返回值:
获取到的单词。
0124-0177
设置编译结果输出目录(make O=out)
uboot 可以将编译出来的目标文件输出到单独的目录中,在 make 的时候使用“O”来指定输出目录,比如“make O=out”就是设置目标文件输出到 out 目录中。这么做是为了将源文件和编译产生的文件分开,当然也可以不指定 O 参数,不指定的话源文件和编译产生的文件都在同一个目录内,一般我们不指定 O 参数。
0178-2315
0178-0181
判断是否跳过 makefile 去输出目录中执行子 makefile
0182-0186
追加 MAKEFLAGS 变量
0187-0202
代码检查(make C=number)
0203-0245
模块编译(make M=dir)
在 Linux 系统中,CD 命令常常被用来切换当前工作目录。然而,当你需要频繁地切换到某个目录时,则需要输入完整路径,这显然不是很方便。为了简化这个过程,Linux 提供了一个叫做 CDPATH 的环境变量,可以让你通过指定一组路径,使 CD 命令可以查找其中的目录并跳转过去。
0246-0262
获取电脑主机架构和系统
0263-0272
设置目标架构、交叉编译器和配置文件
编 译 uboot 的 时 候 需 要 设 置 目 标 板 架 构 和 交 叉 编 译 器 ,“ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-”
就是用于设置 ARCH 和 CROSS_COMPILE,每次编译 uboot 的时候都要在 make 命令后面设置 ARCH 和 CROSS_COMPILE,使用起来很麻烦,可以直接修改顶层 Makefile,在里面加入 ARCH 和 CROSS_COMPILE 的定义,这样就不用每次编译的时候都要在 make 命令后面定义 ARCH 和 CROSS_COMPILE。
ARCH ?= arm
CROSS_COMPILE ?= arm-linux-gnueabihf-
0273-0337
给变量赋值
0338-0383
1. 选择内置编译
2. 编写 sieze_check 函数,并导出
3. 导出相应变量
0384-0387
调用 scripts/Kbuild.include
0388-0425
交叉编译工具变量设置
0426-0449
设置一些变量
$(call 参数1, 参数2, …)
作用:
用于调用一个用户定义的函数,它的第一个参数是函数名,剩下的参数会作为参数传递给函数。
0450-0474
导出其他变量
VERSION: 顶层 Makefile 文件,第3行定义:VERSION = 2021 PATCHLEVEL: 顶层 Makefile 文件,第4行定义:PATCHLEVEL = 07 SUBLEVEL: 顶层 Makefile 文件,第5行定义:SUBLEVEL = UBOOTRELEASE: 顶层 Makefile 文件,由于 include/config/uboot.release 文件是编译后生成的,所以:UBOOTRELEASE= UBOOTVERSION: 顶层 Makefile 文件,第449行定义:UBOOTVERSION = 2021.07 |
ARCH CPU BOARD VENDOR SOC CPUDIR BOARDDIR: 这 7 个变量就是在 config.mk 里面定义的,由于没有引用 config.mk 文件,ARCH 在输入的时候定义为 arm,所以除了 ARCH 其他变量都为空 |
CONFIG_SHELL: 顶层 Makefile 文件,第274行定义:CONFIG_SHELL = /bin/bash HOSTCC: 顶层 Makefile 文件,第282行定义:HOSTCC = cc KBUILD_HOSTCFLAGS: 顶层 Makefile 文件,第284行定义:KBUILD_HOSTCFLAGS := -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer 和 第 297行定义:KBUILD_HOSTCFLAGS += -std=gnu11,所以:KBUILD_HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -std=gnu11 CROSS_COMPILE: 在输入命令行职工定义为:/home/xd/rpi3b/toolchain/toolchain-rpi32b/bin/arm-linux-gnueabihf- AS: 顶层 Makefile 文件,第390行定义:AS = /home/xd/rpi3b/toolchain/toolchain-rpi32b/bin/arm-linux-gnueabihf-as LD: 顶层 Makefile 文件,第393行定义:LD = /home/xd/rpi3b/toolchain/toolchain-rpi32b/bin/arm-linux-gnueabihf-ld.bfdCC: 顶层 Makefile 文件,第397行定义:CC = /home/xd/rpi3b/toolchain/toolchain-rpi32b/bin/arm-linux-gnueabihf-gcc |
CPP: 顶层 Makefile 文件,第398行定义:CPP =/home/xd/rpi3b/toolchain/toolchain-rpi32b/bin/arm-linux-gnueabihf-gcc -EAR: 顶层 Makefile 文件,第399行定义:AR=/home/xd/rpi3b/toolchain/toolchain-rpi32b/bin/arm-linux-gnueabihf-ar NM: 顶层 Makefile 文件,第400行定义:NM= /home/xd/rpi3b/toolchain/toolchain-rpi32b/bin/arm-linux-gnueabihf-nm LDR: 顶层 Makefile 文件,第401行定义:LDR = /home/xd/rpi3b/toolchain/toolchain-rpi32b/bin/arm-linux-gnueabihf-ldr STRIP: 顶层 Makefile 文件,第402行定义:STRIP = /home/xd/rpi3b/toolchain/toolchain-rpi32b/bin/arm-linux-gnueabihf-strip OBJCOPY: 顶层 Makefile 文件,第403行定义:OBJCOPY= /home/xd/rpi3b/toolchain/toolchain-rpi32b/bin/arm-linux-gnueabihf-objcopy OBJDUMP: 顶层 Makefile 文件,第404行定义:OBJDUMP= /home/xd/rpi3b/toolchain/toolchain-rpi32b/bin/arm-linux-gnueabihf-objdump KBUILD_HOSTLDFLAGS: 顶层 Makefile 文件,第287行定义:KBUILD_HOSTLDFLAGS= KBUILD_HOSTLDLIBS: 顶层 Makefile 文件,第288行定义:KBUILD_HOSTLDLIBS= |
MAKE: 内置变量,指向当前使用的 make 工具LEX: 顶层 Makefile 文件,第405行定义:LEX = flexYACC: 顶层 Makefile 文件,第406行定义:YACC = bisonAWK: 顶层 Makefile 文件,第407行定义:AWK= awkPERL: 顶层 Makefile 文件,第408行定义:PERL= perlPYTHON: 顶层 Makefile 文件,第409行定义:PYTHON= pythonPYTHON2: 顶层 Makefile 文件,第410行定义:PYTHON2= python2PYTHON3: 顶层 Makefile 文件,第411行定义:PYTHON3 =python3 |
HOSTCXX: 顶层 Makefile 文件,第283行定义:HOSTCXX = KBUILD_HOSTCXXFLAGS: 顶层 Makefile 文件,第286行定义:KBUILD_HOSTCXXFLAGS=-O2 CHECK: 顶层 Makefile 文件,第413行定义:CHECK= sparseCHECKFLAGS: 顶层 Makefile 文件,第415行定义:CHECKFLAGS = -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ -Wbitwise -Wno-return-void -D__CHECK_ENDIAN__DTC: 顶层 Makefile 文件,第412行定义:DTC= ./scripts/dtc/dtcDTC_FLAGS: 未定义,DTC_FLAGS = |
KBUILD_CPPFLAGS: 顶层 Makefile 文件,第418行定义:KBUILD_CPPFLAGS= -D__KERNEL__ -D__UBOOT__NOSTDINC_FLAGS: 顶层 Makefile 文件,第782行定义:NOSTDINC_FLAGS= -nostdinc -isystem /home/xd/rpi3b/toolchain/toolchain-rpi32b/bin/…/lib/gcc/arm-linux-gnueabihf/7.5.0/include UBOOTINCLUDE: 顶层 Makefile 文件,第771行定义:UBOOTINCLUDE= -Iinclude -I./arch/arm/include -include ./include/linux/kconfig.hOBJCOPYFLAGS: 未定义:OBJCOPYFLAGS=KBUILD_LDFLAGS: 顶层 Makefile 文件,第425行定义:KBUILD_LDFLAGS= |
KBUILD_CFLAGS: 顶层 Makefile 文件,第420行定义:KBUILD_CFLAGS:= -Wall -Wstrict-prototypes -Wno-format-security -fno-builtin -ffreestanding -std=gnu11 ,第423行定义:KBUILD_CFLAGS+= -fshort-wchar -fno-strict-aliasing,第444行定义:KBUILD_CFLAGS+= -fno-PIE,所以:KBUILD_CFLAGS = -Wall -Wstrict-prototypes -Wno-format-security -fno-builtin -ffreestanding -std=gnu11 -fshort-wchar -fno-strict-aliasing -fno-PIEKBUILD_AFLAGS: 顶层 Makefile 文件,第424行定义:KBUILD_AFLAGS:= -D__ASSEMBLY__ ,第445行定义:KBUILD_AFLAGS+= -fno-PIE,所以:KBUILD_AFLAGS = -D__ASSEMBLY__ -fno-PIE |
CC_VERSION_TEXT: 顶层 Makefile 文件,第461行定义:CC_VERSION_TEXT = arm-linux-gnueabihf-gcc (Linaro GCC 7.5-2019.12) 7.5.0 |
MODVERDIR: 顶层 Makefile 文件,第466行定义:MODVERDIR = .tmp_versions |
RCS_FIND_IGNORE: 顶层 Makefile 文件,第470行定义:RCS_FIND_IGNORE= ( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS -o -name .pc -o -name .hg -o -name .git ) -prune -o |
RCS_TAR_IGNORE: 顶层 Makefile 文件,第473行定义:RCS_TAR_IGNORE= --exclude SCCS --exclude BitKeeper --exclude .svn --exclude CVS --exclude .pc --exclude .hg --exclude .git |
0475-0486
目标 scripts_basic 的依赖和实现
第486行:scripts/basic/下的所有文件都依赖 scripts_basic 工具,执行命令为空
展开后make -f ./scripts/Makefile.buid obj=scripts/basic
中 ./scripts/Makefile.buid 的分析
0487-0498
目标 outputmakefile 的依赖和实现
0499-0534
1. 头文件变量赋值
2. 配置方式选择
version_h:这变量保存版本号文件,此文件是自动生成的。
timestamp_h:保存时间戳文件,此文件也是自动生成的。
0535-0550
混合方式 mixed-targets
根据第526-533行分析可知,当输入“make 1_config 2_config”时,有1个以上的%config的配置时,mixed-targets 才会为 1。分别执行“make 1_config” 和“make 2_config”,执行2次。
0551-0565
config 方式
展开后make -f ./scripts/Makefile.buid obj=scripts/kconfig rpi_3_32b_defconfig
中 ./scripts/Makefile.buid 的分析
0566-2218
2219
这是第 535 行:ifeq ($(mixed-targets),1) 的结尾 end
2220-2332
1.追加目标
2.目标的依赖与实现
2233-2351
定义变量 build-dir 和 target-dir
2252-2280
目标的依赖与实现
2281-2314
1. 变量赋值
2. 目标的依赖与实现
3. 查询所有 *.cmd 文件并展开
> $(wildcard <pattern>)
作用:
是Makefile中的一个内建函数,用于获取符合特定模式的文件名列表。
例如:
例如,$(wildcard *.c)会获取当前目录下所有以.c为扩展名的文件列表$(foreach VAR,LIST,TEXT)
作用:
类似于Linux shell中的for语句,是一个循环函数。
函数的工作过程:
执行时把"LIST"中使用空格分隔的字符串依次取出赋值给变量"VAR",然后执行"TEXT"表达式。重复直到"LIST"的最后一个字符串。"TEXT"中的变量或函数引用在执行时才被展开,因此,如果在"TEXT"中存在对"VAR"的引用,那么"VAR"的值在每一次展开时将会是不同的值。如果存在变量或函数的引用,首先需要展开变量"VAR"和"LIST"的引用。函数参数"VAR"是一个局部的临时变量,它只在"foreach"函数的上下文有效,它的定义不影响其他部分定义的同名"VAR"变量的值。
$(sort list)
作用:
是Makefile的一个内建函数,它用于将列表中的词进行排序,并删除重复的词。
参数:
list是你想要排序的单词列表
$(dir <names…>)
作用:
从文件名序列中取出目录部分。目录部分是指最后一个反斜杠(/)之前的部分。如果没有反斜杠,那么返回./。
返回值:
返回文件名序列的目录部分
$(notdir <names…>)
作用:
从文件名序列中取出非目录部分。非目录部分是指最后一个反斜杠(/)之后的部分。
返回值:
返回文件名序列的非目录部分
2315
第180行 ifeq ($(skip-makefile),) 的结尾 endif
2316-2323
目标文件