uboot顶层makefile走读

1

1.1

MAKEFLAGS += -rR --include-dir=$(CURDIR)

MAKEFLAGS和CURDIR为makefile中的默认变量

使用make -.p可以查看makefile预先定义过的东西

1.2

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

这段代码实现了在make的时候使用参数V=1或者V=0实现长短命令log输出切换

原理是通过命令行传进来的V参数构造KBUILD_VERBOSE quiet Q三个变量

在写命令的时候加上$(Q)或者$(quiet)前缀,使得命令文本变成短命令打印的版本

V=0:$(Q)make------->@make        @(quiet)sym------->quiet_sym

V=1:$(Q)make------->make            @(quiet)sym------->sym

uboot编译时可加上-s变成静默编译,原理是凑出silent_前缀

export quiet Q KBUILD_VERBOSE

之后通过export把这三个变量传给下层makefile

1.3

ifeq ($(KBUILD_SRC),)
        # building in the source tree
        srctree := .
else
        ifeq ($(KBUILD_SRC)/,$(dir $(CURDIR)))
                # building in a subdirectory of the source tree
                srctree := ..
        else
                srctree := $(KBUILD_SRC)
        endif
endif
objtree		:= .
src		:= $(srctree)
obj		:= $(objtree)

VPATH		:= $(srctree)$(if $(KBUILD_EXTMOD),:$(KBUILD_EXTMOD))

export srctree objtree VPATH

生成源代码路径,和生成文件路径以及VPATH

1.4

HOSTARCH := $(shell uname -m | \
	sed -e s/i.86/x86/ \
	    -e s/sun4u/sparc64/ \
	    -e s/arm.*/arm/ \
	    -e s/sa110/arm/ \
	    -e s/ppc64/powerpc/ \
	    -e s/ppc/powerpc/ \
	    -e s/macppc/powerpc/\
	    -e s/sh.*/sh/)

HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \
	    sed -e 's/\(cygwin\).*/cygwin/')

export	HOSTARCH HOSTOS

这里是检测host主机,也就是编译用主机的系统和架构

1.5

KCONFIG_CONFIG	?= .config
export KCONFIG_CONFIG

将.config文件名作为变量KCONFIG_CONFIG导入,这个是正式编译前进行编译配置自动生成的,为关键文件之一

1.6

HOSTCC       = cc
HOSTCXX      = c++
HOSTCFLAGS   = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
HOSTCXXFLAGS = -O2
HOSTCC       = $(call os_x_before, 10, 5, "cc", "gcc")
HOSTCFLAGS  += $(call os_x_before, 10, 4, "-traditional-cpp")
HOSTLDFLAGS += $(call os_x_before, 10, 5, "-multiply_defined suppress")

生成host的gcc命令

CC		= $(CROSS_COMPILE)gcc
CPP		= $(CC) -E
AR		= $(CROSS_COMPILE)ar
NM		= $(CROSS_COMPILE)nm
LDR		= $(CROSS_COMPILE)ldr
STRIP		= $(CROSS_COMPILE)strip
OBJCOPY		= $(CROSS_COMPILE)objcopy
OBJDUMP		= $(CROSS_COMPILE)objdump

生成交叉编译的gcc命令

export ARCH CPU BOARD VENDOR SOC CPUDIR BOARDDIR
export CONFIG_SHELL HOSTCC HOSTCFLAGS HOSTLDFLAGS CROSS_COMPILE AS LD CC
export CPP AR NM LDR STRIP OBJCOPY OBJDUMP

将生成的命令变量export到下层makefile,同时export的还有目标平台的ARCH、CPU、BOARD等信息(第一行),这些信息在1.7小节介绍的代码中生成

1.7

include/config/%.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd
	$(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig
	@# If the following part fails, include/config/auto.conf should be
	@# deleted so "make silentoldconfig" will be re-run on the next build.
	$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.autoconf || \
		{ rm -f include/config/auto.conf; false; }
	@# include/config.h has been updated after "make silentoldconfig".
	@# We need to touch include/config/auto.conf so it gets newer
	@# than include/config.h.
	@# Otherwise, 'make silentoldconfig' would be invoked twice.
	$(Q)touch include/config/auto.conf

第5行将script/Makefile.autoconf使用-f作为makefile,这个文件中导入了config.mk

ifneq ($(wildcard $(KCONFIG_CONFIG)),)
ifneq ($(wildcard include/config/auto.conf),)
autoconf_is_old := $(shell find . -path ./$(KCONFIG_CONFIG) -newer \
						include/config/auto.conf)
ifeq ($(autoconf_is_old),)
include config.mk
include arch/$(ARCH)/Makefile
endif
endif
endif

1.6小节中,目标平台的ARCH、CPU、BOARD等信息会在config.mk文件中生成,以上代码导入了config.mk文件

以下为config.mk中生成这几个变量的代码

ARCH := $(CONFIG_SYS_ARCH:"%"=%)
CPU := $(CONFIG_SYS_CPU:"%"=%)
ifdef CONFIG_SPL_BUILD
ifdef CONFIG_TEGRA
CPU := arm720t
endif
endif
BOARD := $(CONFIG_SYS_BOARD:"%"=%)
ifneq ($(CONFIG_SYS_VENDOR),)
VENDOR := $(CONFIG_SYS_VENDOR:"%"=%)
endif
ifneq ($(CONFIG_SYS_SOC),)
SOC := $(CONFIG_SYS_SOC:"%"=%)
endif

config.mk中使用的变量由.config文件生成

CONFIG_SYS_ARCH="arm"
CONFIG_SYS_CPU="armv7"
CONFIG_SYS_SOC="mx6"
CONFIG_SYS_VENDOR="freescale"
CONFIG_SYS_BOARD="mx6ull_alientek_emmc"
CONFIG_SYS_CONFIG_NAME="mx6ull_alientek_emmc"

2

2.1

make xxx_defconfig命令时生成.config,主要执行了如下规则

%config: scripts_basic outputmakefile FORCE
	$(Q)$(MAKE) $(build)=scripts/kconfig $@

其中依赖以下三条规则

PHONY += FORCE
FORCE:
PHONY += scripts_basic
scripts_basic:
	$(Q)$(MAKE) $(build)=scripts/basic
	$(Q)rm -f .tmp_quiet_recordmcount
PHONY += outputmakefile
# outputmakefile generates a Makefile in the output directory, if using a
# separate output directory. This allows convenient use of make in the
# output directory.
outputmakefile:
ifneq ($(KBUILD_SRC),)
	$(Q)ln -fsn $(srctree) source
	$(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile \
	    $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL)
endif

第一规则(FORCE)和第三规则(outputmakefile)实际执行了空命令,对结果没有影响,因此主要生成了第二个规则(scripts_basic)对应的文件

$(build)变量定义在script/Kbuild.include文件中

###
# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj=
# Usage:
# $(Q)$(MAKE) $(build)=dir
build := -f $(srctree)/scripts/Makefile.build obj

该文件在顶层makefile中已经被导入

# We need some generic definitions (do not try to remake the file).
scripts/Kbuild.include: ;
include scripts/Kbuild.include

因此

在规则scripts_basic中,最终执行的命令如下

make -f ./scripts/Makefile.build obj=scripts/basic

在规则%config中,最终执行的命令如下

make -f ./scripts/Makefile.build obj=scripts/kconfig %_defconfig

可见执行的都是./scripts/Makefile.build这个文件,同时传入了不同的obj作为参赛

2.2

./scripts/Makefile.build文件中,一开始的代码如下

prefix := tpl
src := $(patsubst $(prefix)/%,%,$(obj))
ifeq ($(obj),$(src))
prefix := spl
src := $(patsubst $(prefix)/%,%,$(obj))
ifeq ($(obj),$(src))
prefix := .
endif
endif

以上代码用于去掉obj中的tpl和spl前缀

# 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)

对于第2.1节中的两个make过程,kbuid-file分别为scripts/basic/Makefile和scripts/kconfig/Makefile

__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
	 $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
	 $(subdir-ym) $(always)
	@:

2.3

 scripts/basic/Makefile

hostprogs-y	:= fixdep
always		:= $(hostprogs-y)

# fixdep is needed to compile other host programs
$(addprefix $(obj)/,$(filter-out fixdep,$(always))): $(obj)/fixdep

scripts/kconfig/Makefile

%_defconfig: $(obj)/conf
	$(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)

# Added for U-Boot (backward compatibility)
%_config: %_defconfig
	@:

你可能感兴趣的:(嵌入式linux,gnu)