1.MAKEFLAGS变量
主目录的 Makefile 可以使用如下 代码来编译这个子目录:
$(MAKE) -C subdir
$(MAKE)就是调用“make”命令,-C 指定子目录。
有时候我们需要向子 make 传递变量,export/unexport
export VARIABLE ……
//导出变量给子 make 。
unexport VARIABLE……
//不导出变量给子 make。
有两个特殊的变量:“SHELL”和“MAKEFLAGS”,这两个变量除非使用“unexport”声明, 否则的话在整个make的执行过程中,它们的值始终自动的传递给子make
MAKEFLAGS += -rR --include-dir=$(CURDIR)
上述代码使用“+=”来给变量 MAKEFLAGS 追加了一些值,“ -rR”表示禁止使用内置的隐 含规则和变量定义,“--include-dir”指明搜索路径,”$(CURDIR)”表示当前目录。
2.命令输出 V=1
ifeq ("$(origin V)", "command line")
KBUILD_VERBOSE = $(V)
endif
ifndef KBUILD_VERBOSE
KBUILD_VERBOSE = 0
endif
ifeq ($(KBUILD_VERBOSE),1)
quiet =
Q =
else
quiet=quiet_
Q = @
endif
先使用 ifeq 来判断"$(origin V)"和"command line"是否相等。这里用到了 Makefile 中的函数 origin,origin 和其他的函数不一样,它不操作变量的值,origin 用于告诉你变量是哪来的,语法为:
$(origin <variable>)
//variable 是变量名,origin 函数的返回值就是变量来源,因此$(origin V)就是变量 V 的来源。
如果变量 V 是在命令行定义的那么它的来源就是"command line",这样"$(origin V)"和"command line"就相等了。
3.静默输出 make -s
ifneq ($(filter 4.%,$(MAKE_VERSION)),) # make-4
ifneq ($(filter %s ,$(firstword x$(MAKEFLAGS))),) #过滤出%s的单词
quiet=silent_
endif
else # make-3.8x
ifneq ($(filter s% -s%,$(MAKEFLAGS)),)
quiet=silent_
endif
endif
export quiet Q KBUILD_VERBOSE
$(filter <pattern...>,<text>)
filter 函数表示以 pattern 模式过滤 text 字符串中的单词,仅保留符合模式 pattern 的单词, 可以有多个模式。
因此$(filter 4.%,$(MAKE_VERSION)) 的含义就是在字符串“MAKE_VERSION”中找出符合“4.%”的字符(%为通配符), MAKE_VERSION 是make工具的版本号,ubuntu16.04里面默认自带的make工具版本号为4.1, 大家可以输入“make -v”查看。因此$(filter4.%,$(MAKE_VERSION))不为空,条件成立。
$(firstword <text>)
firstword 函数用于取出 text 字符串中的第一个单词,函数的返回值就是获取到的单词。
4.设置编译结果输出目录
uboot 可以将编译出来的目标文件输出到单独的目录中,在 make 的时候使用“O”来指定 输出目录,比如“make O=out”。
5.代码检查
uboot 支持代码检查,使用命令“make C=1”使能代码检查,检查那些需要重新编译的文 件。“make C=2”用于检查所有的源码文件
6.模块编译
在 uboot 中允许单独编译某个模块,使用命令“make M=dir”即可,旧语法“make SUBDIRS=dir”也是支持的。
ifdef SUBDIRS
KBUILD_EXTMOD ?= $(SUBDIRS)
endif
ifeq ("$(origin M)", "command line")
KBUILD_EXTMOD := $(M)
endif
7.设置目标架构、交叉编译器和配置文件
编 译 uboot 的 时 候 需 要 设 置 目 标 板 架 构 和 交 叉 编 译 器 ,“ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-”就是用于设置 ARCH 和 CROSS_COMPILE.
245行判断 HOSTARCH 和 ARCH 这两个变量是否相等,主机架构(变量 HOSTARCH)是
x86_64,而我们编译的是 ARM 版本 uboot,肯定不相等。
252行行定义变量 KCONFIG_CONFIG,uboot 是可以配置的,这里设置配置文件为.config,.config 默认是没有的,需要使用命令“make xxx_defconfig”对 uboot 进行配置,配置完成以后就会在 uboot 根目录下生成.config。
默认情况下.config 和xxx_defconfig 内容是一样的,因为.config 就是从 xxx_defconfig 复制过来的。如果后续自行调整了 uboot 的一些配置参数,那么这些新的配置参数就添加到了.config 中,而不是 xxx_defconfig。相当于 xxx_defconfig 只是一些初始配置,而.config 里面的才是实时有效的配置。
8.make xxx_defconfig
make xxx_defconfig配置 uboot 的时候如下两行命令会执行脚本
scripts/Makefile.build:
@make -f ./scripts/Makefile.build obj=scripts/basic
@make -f ./scripts/Makefile.build obj=scripts/kconfig xxx_defconfig
2.
9.make过程
u-boot.bin: u-boot-nodtb.bin FORCE
u-boot-nodtb.bin: u-boot FORCE
u-boot: $(u-boot-init) $(u-boot-main) u-boot.lds FORCE
u-boot-init := $(head-y)
u-boot-main := $(libs-y)
head-y := arch/arm/cpu/armv7/start.o
libs-y 都是 uboot 各子目录的集合,最后:
libs-y := $(patsubst %/, %/built-in.o, $(libs-y))
这里调用了函数 patsubst,将 libs-y 中的“/”替换为”/built-in.o”,比
因此,这个规则就相当于将以 u-boot.lds 为链接脚本,将 arch/arm/cpu/armv7/start.o 和各个子目录下的 built-in.o 链接在一起生成 u-boot。
make xxx_defconfig:用于配置 uboot,这个命令最主要的目的就是生成.config 文件。
make:用于编译 uboot,这个命令的主要工作就是生成二进制的 u-boot.bin 文件和其他的一
些与 uboot 有关的文件,比如 u-boot.imx 等等。