uboot系列之-----顶层Makefile分析(二)

来源:互联网 发布:java特种兵 读后感 编辑:程序博客网 时间:2024/04/30 01:28

继续上篇,这篇主要分析跟编译和连接库文件相关的变量

ifeq ($(obj)include/config.mk,$(wildcard $(obj)include/config.mk))

……

else  # !config.mk

all $(obj)u-boot.hex $(obj)u-boot.srec $(obj)u-boot.bin \

$(obj)u-boot.img $(obj)u-boot.dis $(obj)u-boot \

$(filter-out tools,$(SUBDIRS)) $(TIMESTAMP_FILE) $(VERSION_FILE) \

updater depend dep tags ctags etags cscope $(obj)System.map:

         @echo "System not configured - see README" >&2

         @ exit 1

 

tools:

         $(MAKE) -C $@ all

endif # config.mk

ifeq语句判断include目录下是否存在config.mk文件(通过《uboot系列之-----uboot配置过程详细分析》一文可知,只有执行了make xxx_config之后,才存在该文件)。

我们暂时不分析config.mk存在时的情况,因为太长了,先分析config.mk不存在的情况,即else后的语句,该语句把所有的目标都指向了一个依赖,就是打印出错信息“System not configured – see README”,然后退出。

接下来看config.mk存在的情况:

all:

sinclude $(obj)include/autoconf.mk.dep

sinclude $(obj)include/autoconf.mk

先看目标all:makefile开始到现在,发现这个all是第一个目标,也就是说当我们执行make命令时,它是默认目标,但是该目标既没有依赖也没有规则,那它起到什么作用呢?接着往下看,sinclude $(obj)include/autoconf.mk.dep,他的意思是包含autoconf.mk.dep文件,进入到该文件,发现第一句是:

include/autoconf.mk: include/common.h \,它也是一个目标,并且有很多的依赖

再回到all的作用上来,如果没有这个all,那么当我们执行make时,根据make法则,(它将第一个目标作为他的默认目标),也就是将autoconf.mk作为默认目标,显然这不是我们想要的结果,(我们执行make是想编译整个文件,也就是执行第365行的all: $(ALL)这个规则,而在这里加上一个看起来“毫无意义”的all,就能达到我们想要的目的,即执行第一个空的all目标后,会跳过autoconf.mk目标,执行下一个all目标)

再来看sincludesinclude也是包含文件的关键词,他与include的区别就是使用sinclude时,即使所需要包含的文件不存在,也不影响makefile的往下执行。

autoconf.mk.depautoconf.mk这两个文件是怎么来的呢,makefile中有如下一段语句,说明了这两个文件的来源:

$(obj)include/autoconf.mk.dep: $(obj)include/config.h include/common.h

        @$(XECHO) Generating $@ ; \

         set -e ; \

         : Generate the dependancies ; \

         $(CC) -x c -DDO_DEPS_ONLY -M $(HOSTCFLAGS) $(CPPFLAGS) \

                  -MQ $(obj)include/autoconf.mk include/common.h > $@

 

$(obj)include/autoconf.mk: $(obj)include/config.h

         @$(XECHO) Generating $@ ; \

         set -e ; \

         : Extract the config macros ; \

         $(CPP) $(CFLAGS) -DDO_DEPS_ONLY -dM include/common.h | \

                  sed -n -f tools/scripts/define2mk.sed > $@.tmp && \

         mv $@.tmp $@

这段规则没有完全看明白,望大侠们帮我分析一下

include $(obj)include/config.mk

export       ARCH CPU BOARD VENDOR SOC

包含配置过程中生成的config.mk文件,并把该文件中的变量导出来

ifeq ($(ARCH),arm)

CROSS_COMPILE =/usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-

Endif

如果ARCH=arm,即体系架构为ARM ,就给变量CROSS_COMPILE赋值,改变量的值代表了交叉编译器的路径

include $(TOPDIR)/config.mk

包含顶层目录下的config.mk文件

 

下面开始定义了目标文件变量(跟ARM无关的这里就省略没有列出来)

OBJS  = $(CPUDIR)/start.o

这里的CPUDIR目录在顶层目录的config.mk文件里面定义 CPUDIR=arch/$(ARCH)/cpu/$(CPU),对于smdk4412来说 CPUDIR= arch/arm/cpu/armv7

……

OBJS := $(addprefix $(obj),$(OBJS))

在原有OBJS值前面加上一个路径$(obj)前缀,指明绝对路径,如果$(obj)为空,则OBJS相当于没变化

下面开始定义了库文件变量(跟硬件平台无关的这里就省略没有列出来)

…….

LIBS += $(shell if [ -f board/$(VENDOR)/common/Makefile ]; then echo \

        "board/$(VENDOR)/common/lib$(VENDOR).o"; fi)

LIBS += $(CPUDIR)/lib$(CPU).o

ifdef SOC

LIBS += $(CPUDIR)/$(SOC)/lib$(SOC).o

Endif

对于smdk4412来说,board/Samsung/common/Makefile文件并不存在,所以第一个赋值无效,接下来的两个分别为

LIBS+= arch/arm/cpu/armv7/libarmv7.o

LIBS+= arch/arm/cpu/armv7/exynos/libexynos.o

…..

LIBS += arch/$(ARCH)/lib/lib$(ARCH).o

LIBS+= arch/arm/lib/libarm.o

ifeq ($(SOC),exynos)

LIBS += $(CPUDIR)/s5p-common/libs5p-common.o

Endif

LIBS+= arch/arm/cpu/armv7/s5p-common/libs5p-common.o

LIBBOARD = board/$(BOARDDIR)/lib$(BOARD).o

LIBBOARD := $(addprefix $(obj),$(LIBBOARD))

BOARDDIR定义在顶层目录的config.mk文件 BOARDDIR = $(VENDOR)/$(BOARD) 对于smdk4412来说

BOARDDIR = Samsung/smdk4212

LIBBOARD = board/samsung/smdk4212/libsmdk4212.o

 

PLATFORM_LIBGCC = -L $(shell dirname `$(CC) $(CFLAGS) -print-libgcc-file-name`) –lgcc

PLATFORM_LIBS += $(PLATFORM_LIBGCC)

export PLATFORM_LIBS

dirname `$(CC) $(CFLAGS) -print-libgcc-file-name`取得交叉编译器的libgcc.a的绝对路径

$(CC) = $(CROSS_COMPILE)gcc

$(CFLAGS)定义在config.mk

-L表示编译时将其后所跟的目录作为第一个寻找库文件的目录

LDPPFLAGS += \

        -include $(TOPDIR)/include/u-boot/u-boot.lds.h \

         $(shell $(LD) --version | \

           sed -ne 's/GNU ld version \([0-9][0-9]*\)\.\([0-9][0-9]*\).*/-DLD_MAJOR=\1 -DLD_MINOR=\2/p')

$(LD)定义在顶层目录的config.mk文件

LD= $(CROSS_COMPILE)ld,表示交叉编译器里面的连接工具

shell $(LD) –version表示取得连接工具的版本,我这里的版本号是GNU ld (GNU Binutils for Ubuntu) 2.22”

ifeq ($(CONFIG_NAND_U_BOOT),y)

NAND_SPL = nand_spl

U_BOOT_NAND = $(obj)u-boot-nand.bin

endif

 

ifeq ($(CONFIG_ONENAND_U_BOOT),y)

ONENAND_IPL = onenand_ipl

U_BOOT_ONENAND = $(obj)u-boot-onenand.bin

ONENAND_BIN ?= $(obj)onenand_ipl/onenand-ipl-2k.bin

endif

 

__OBJS := $(subst $(obj),,$(OBJS))

__LIBS := $(subst $(obj),,$(LIBS)) $(subst $(obj),,$(LIBBOARD))

$subst(<from>,<to>,<text>)的功能是将<text>中的<from>字符串换成<to>字符串

__OBJS相当于截取OBJS的相对路径__LIBS类似

 

 

原创粉丝点击