u-boot编译(一)

 u-boot编译(一)

 
接着“详解u-boot配置(一)”分析Makefile文件。
1.接下来就是ifeq  else  endif 语句了,这段代码可够长的,三百多行了都,我们还是一段段来分析吧。
 
ifeq ($(obj)include/config.mk,$(wildcard $(obj)include/config.mk))
else
endif
 
相信大家对ifeq(,)都不陌生了,但是$(wildcard $(obj)include/config.mk)这是什么鬼啊?这是函数wildcard啦,怎么使用,这里简单说一下(更详细的可以看GNU make使用手册)。
 
函数wildcard,格式如下:
$(wildcard pattern...)
使用方法:可以在makefile文件的任何地方使用该字符串,应用时该字符串被一列在指定目录下存在的并且文件名和给出的文件名的格式相符合的文件所代替,文件名中间由空格隔开。如果没有和指定格式一致的文件,则函数wildcard的输出将会省略。
也就是到$(obj)include目录下查看有没有config.mk这个文件,如果有就输出$(obj)include/config.mk,如果没有则输出将会省略。
再配合上ifeq(,)应该很容易就能理解了,但是我们得明白为什么要这么做,想想也不难,因为我们在u-boot配置的时候已经知道config.mk是如何创建起来的,再看看else分支里面有这么一句话:   @echo "System not configured - see README",告诉你系统没有配置呢。很显然如果你没有配置就要你先配置u-boot,再来编译。
但是反过来,有一个更值得我们思考的问题,为什么在配置u-boot的时候没有出现这样的报错情况呢?同样在配置之前include目录下并没有config.mk文件呢,敢问这又何解(下面将会分析这个问题)?要想弄清这个问题,就得知道是如何运行make的。好了,我们来看一个有趣的例子,也许能引发出更多的思考,请看下面的“实验(一)”。
对于如何运行make(也就是makefile的执行顺序,它可并不是我们想象中的顺序执行哦)且看这篇博文:linux下makefile的执行顺序。
(1)先来看一下else分支做了什么事,代码如下:
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) gdbtools \
updater env depend dep tags ctags etags cscope $(obj)System.map:
 @echo "System not configured - see README" >&2
 @ exit 1

这是一个具有多目标规则的目标,具有多个目标的规则等同于写多条规则,这些规则除了目标不同之外,其余部分完全相同。相同的命令应用于所有目标,但命令执行的结果可能有所差异,这条规则同样意味着所有的目标有相同的依赖。

可以看到我们上面的这些目标并没有依赖文件,但是他们具有相同的命令。再细心点你可能会发现,这些目标都是在了ifeq分支里(注意这跟上边的问题是有联系的)。

现在我们可以回答上面的问题了,就是为什么同样在没有config.mk文件存在时,配置u-boot却不报错,因为这些都是目标,但我们不执行上面这些目标,那就不回执行目标下的命令的,当你执行make命令时,默认是执行all这个目标,看到了吧,else分支里也有all目标了,所以你在配置u-boot时,虽然进入了else分支里,但是并没有我们要执行的目标,自然就不执行后面的报错和退出命令了。

 

(2)分析完else分支,再来分析ifeq分支了。

代码如下:

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

# load ARCH, BOARD, and CPU configuration
include $(obj)include/config.mk
export ARCH CPU BOARD VENDOR SOC

CROSS_COMPILE = arm-linux-

# set default to nothing for native builds
ifeq ($(HOSTARCH),$(ARCH))
CROSS_COMPILE ?=
endif

# load other configuration
include $(TOPDIR)/config.mk

#########################################################################
# U-Boot objects....order is important (i.e. start must be first)

OBJS  = cpu/$(CPU)/start.o
ifeq ($(CPU),i386)
OBJS += cpu/$(CPU)/start16.o
OBJS += cpu/$(CPU)/resetvec.o
endif
ifeq ($(CPU),ppc4xx)
OBJS += cpu/$(CPU)/resetvec.o
endif
ifeq ($(CPU),mpc85xx)
OBJS += cpu/$(CPU)/resetvec.o
endif

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

LIBS  = lib_generic/libgeneric.a
LIBS += lib_generic/lzma/liblzma.a
LIBS += lib_generic/lzo/liblzo.a
LIBS += $(shell if [ -f board/$(VENDOR)/common/Makefile ]; then echo \
 "board/$(VENDOR)/common/lib$(VENDOR).a"; fi)
LIBS += cpu/$(CPU)/lib$(CPU).a
ifdef SOC
LIBS += cpu/$(CPU)/$(SOC)/lib$(SOC).a
endif
ifeq ($(CPU),ixp)
LIBS += cpu/ixp/npe/libnpe.a
endif
LIBS += lib_$(ARCH)/lib$(ARCH).a
LIBS += fs/cramfs/libcramfs.a fs/fat/libfat.a fs/fdos/libfdos.a fs/jffs2/libjffs2.a \
 fs/reiserfs/libreiserfs.a fs/ext2/libext2fs.a fs/yaffs2/libyaffs2.a \
 fs/ubifs/libubifs.a
LIBS += net/libnet.a
LIBS += disk/libdisk.a
LIBS += drivers/bios_emulator/libatibiosemu.a
LIBS += drivers/block/libblock.a
LIBS += drivers/dma/libdma.a
LIBS += drivers/fpga/libfpga.a
LIBS += drivers/gpio/libgpio.a
LIBS += drivers/hwmon/libhwmon.a
LIBS += drivers/i2c/libi2c.a
LIBS += drivers/input/libinput.a
LIBS += drivers/misc/libmisc.a
LIBS += drivers/mmc/libmmc.a
LIBS += drivers/mtd/libmtd.a
LIBS += drivers/mtd/nand/libnand.a
LIBS += drivers/mtd/onenand/libonenand.a
LIBS += drivers/mtd/ubi/libubi.a
LIBS += drivers/mtd/spi/libspi_flash.a
LIBS += drivers/net/libnet.a
LIBS += drivers/net/phy/libphy.a
LIBS += drivers/pci/libpci.a
LIBS += drivers/pcmcia/libpcmcia.a
LIBS += drivers/power/libpower.a
LIBS += drivers/spi/libspi.a
ifeq ($(CPU),mpc83xx)
LIBS += drivers/qe/qe.a
endif
ifeq ($(CPU),mpc85xx)
LIBS += drivers/qe/qe.a
LIBS += cpu/mpc8xxx/ddr/libddr.a
LIBS += cpu/mpc8xxx/lib8xxx.a
endif
ifeq ($(CPU),mpc86xx)
LIBS += cpu/mpc8xxx/ddr/libddr.a
LIBS += cpu/mpc8xxx/lib8xxx.a
endif
LIBS += drivers/rtc/librtc.a
LIBS += drivers/serial/libserial.a
LIBS += drivers/twserial/libtws.a
LIBS += drivers/usb/gadget/libusb_gadget.a
LIBS += drivers/usb/host/libusb_host.a
LIBS += drivers/usb/musb/libusb_musb.a
 
# Apollo +
LIBS += drivers/usb/slave/libusb_slave.a
# Apollo -

LIBS += drivers/usb/phy/libusb_phy.a
LIBS += drivers/video/libvideo.a
LIBS += drivers/watchdog/libwatchdog.a
LIBS += common/libcommon.a
LIBS += libfdt/libfdt.a
LIBS += api/libapi.a
LIBS += post/libpost.a

LIBS := $(addprefix $(obj),$(LIBS))
.PHONY : $(LIBS) $(TIMESTAMP_FILE) $(VERSION_FILE)

LIBBOARD = board/$(BOARDDIR)/lib$(BOARD).a
LIBBOARD := $(addprefix $(obj),$(LIBBOARD))

# Add GCC lib
ifdef USE_PRIVATE_LIBGCC
ifeq ("$(USE_PRIVATE_LIBGCC)", "yes")
PLATFORM_LIBGCC = -L $(OBJTREE)/lib_$(ARCH) -lgcc
else
PLATFORM_LIBGCC = -L $(USE_PRIVATE_LIBGCC) -lgcc
endif
else
PLATFORM_LIBGCC = -L $(shell dirname `$(CC) $(CFLAGS) -print-libgcc-file-name`) -lgcc
endif
PLATFORM_LIBS += $(PLATFORM_LIBGCC)
export PLATFORM_LIBS

# Special flags for CPP when processing the linker script.
# Pass the version down so we can handle backwards compatibility
# on the fly.
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')

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

#########################################################################
#########################################################################

# Always append ALL so that arch config.mk's can add custom ones
ALL += $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND) $(U_BOOT_ONENAND)

all:  $(ALL)

$(obj)u-boot.hex: $(obj)u-boot
  $(OBJCOPY) ${OBJCFLAGS} -O ihex $< $@

$(obj)u-boot.srec: $(obj)u-boot
  $(OBJCOPY) -O srec $< $@

$(obj)u-boot.bin: $(obj)u-boot
  $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@

$(obj)u-boot.ldr: $(obj)u-boot
  $(CREATE_LDR_ENV)
  $(LDR) -T $(CONFIG_BFIN_CPU) -c $@ $< $(LDR_FLAGS)

$(obj)u-boot.ldr.hex: $(obj)u-boot.ldr
  $(OBJCOPY) ${OBJCFLAGS} -O ihex $< $@ -I binary

$(obj)u-boot.ldr.srec: $(obj)u-boot.ldr
  $(OBJCOPY) ${OBJCFLAGS} -O srec $< $@ -I binary

$(obj)u-boot.img: $(obj)u-boot.bin
  ./tools/mkimage -A $(ARCH) -T firmware -C none \
  -a $(TEXT_BASE) -e 0 \
  -n $(shell sed -n -e 's/.*U_BOOT_VERSION//p' $(VERSION_FILE) | \
   sed -e 's/"[  ]*$$/ for $(BOARD) board"/') \
  -d $< $@

$(obj)u-boot.imx:       $(obj)u-boot.bin
  $(obj)tools/mkimage -n $(IMX_CONFIG) -T imximage \
  -e $(TEXT_BASE) -d $< $@

$(obj)u-boot.kwb:       $(obj)u-boot.bin
  $(obj)tools/mkimage -n $(KWD_CONFIG) -T kwbimage \
  -a $(TEXT_BASE) -e $(TEXT_BASE) -d $< $@

$(obj)u-boot.sha1: $(obj)u-boot.bin
  $(obj)tools/ubsha1 $(obj)u-boot.bin

$(obj)u-boot.dis: $(obj)u-boot
  $(OBJDUMP) -d $< > $@

GEN_UBOOT = \
  UNDEF_SYM=`$(OBJDUMP) -x $(LIBBOARD) $(LIBS) | \
  sed  -n -e 's/.*\($(SYM_PREFIX)__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\
  cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) \
   --start-group $(__LIBS) --end-group $(PLATFORM_LIBS) \
   -Map u-boot.map -o u-boot
$(obj)u-boot: depend $(SUBDIRS) $(OBJS) $(LIBBOARD) $(LIBS) $(LDSCRIPT) $(obj)u-boot.lds
  $(GEN_UBOOT)
ifeq ($(CONFIG_KALLSYMS),y)
  smap=`$(call SYSTEM_MAP,u-boot) | \
   awk '$$2 ~ /[tTwW]/ {printf $$1 $$3 "
\\\\000"}'` ; \
  $(CC) $(CFLAGS) -DSYSTEM_MAP="\"$${smap}\"" \
   -c common/system_map.c -o $(obj)common/system_map.o
  $(GEN_UBOOT) $(obj)common/system_map.o
endif

$(OBJS): depend
  $(MAKE) -C cpu/$(CPU) $(if $(REMOTE_BUILD),$@,$(notdir $@))

$(LIBS): depend $(SUBDIRS)
  $(MAKE) -C $(dir $(subst $(obj),,$@))

$(LIBBOARD): depend $(LIBS)
  $(MAKE) -C $(dir $(subst $(obj),,$@))

$(SUBDIRS): depend
  $(MAKE) -C $@ all

$(LDSCRIPT): depend
  $(MAKE) -C $(dir $@) $(notdir $@)

$(obj)u-boot.lds: $(LDSCRIPT)
  $(CPP) $(CPPFLAGS) $(LDPPFLAGS) -ansi -D__ASSEMBLY__ -P - <$^ >$@

$(NAND_SPL): $(TIMESTAMP_FILE) $(VERSION_FILE) $(obj)include/autoconf.mk
  $(MAKE) -C nand_spl/board/$(BOARDDIR) all

$(U_BOOT_NAND): $(NAND_SPL) $(obj)u-boot.bin
  cat $(obj)nand_spl/u-boot-spl-16k.bin $(obj)u-boot.bin > $(obj)u-boot-nand.bin

$(ONENAND_IPL): $(TIMESTAMP_FILE) $(VERSION_FILE) $(obj)include/autoconf.mk
  $(MAKE) -C onenand_ipl/board/$(BOARDDIR) all

$(U_BOOT_ONENAND): $(ONENAND_IPL) $(obj)u-boot.bin
  cat $(ONENAND_BIN) $(obj)u-boot.bin > $(obj)u-boot-onenand.bin

$(VERSION_FILE):
  @( printf '#define U_BOOT_VERSION "U-Boot %s%s"\n' "$(U_BOOT_VERSION)" \
   '$(shell $(TOPDIR)/tools/setlocalversion $(TOPDIR))' ) >
 [email protected]
  @cmp -s $@ [email protected] && rm -f [email protected] || mv -f [email protected] $@

$(TIMESTAMP_FILE):
  @date +'#define U_BOOT_DATE "%b %d %C%y"' > $@
  @date +'#define U_BOOT_TIME "%T"' >> $@

gdbtools:
  $(MAKE) -C tools/gdb all || exit 1

updater:
  $(MAKE) -C tools/updater all || exit 1

env:
  $(MAKE) -C tools/env all MTD_VERSION=${MTD_VERSION} || exit 1

# Explicitly make _depend in subdirs containing multiple targets to prevent
# parallel sub-makes creating .depend files simultaneously.
depend dep: $(TIMESTAMP_FILE) $(VERSION_FILE) $(obj)include/autoconf.mk
  for dir in $(SUBDIRS) cpu/$(CPU) $(dir $(LDSCRIPT)) ; do \
   $(MAKE) -C $$dir _depend ; done

TAG_SUBDIRS = $(SUBDIRS)
TAG_SUBDIRS += $(dir $(__LIBS))
TAG_SUBDIRS += include

tags ctags:
  ctags -w -o $(obj)ctags `find $(TAG_SUBDIRS) \
      -name '*.[chS]' -print`

etags:
  etags -a -o $(obj)etags `find $(TAG_SUBDIRS) \
      -name '*.[chS]' -print`
cscope:
  find $(TAG_SUBDIRS) -name '*.[chS]' -print > cscope.files
  cscope -b -q -k

SYSTEM_MAP = \
  $(NM) $1 | \
  grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | \
  LC_ALL=C sort
$(obj)System.map: $(obj)u-boot
  @$(call SYSTEM_MAP,$<) > $(obj)System.map

#
# Auto-generate the autoconf.mk file (which is included by all makefiles)
#
# This target actually generates 2 files; autoconf.mk and autoconf.mk.dep.
# the dep file is only include in this top level makefile to determine when
# to regenerate the autoconf.mk file.
$(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 >
 [email protected] && \
 mv
 [email protected] $@

#########################################################################

奇怪,怎么这个分支里有两个all:目标,这又是这么回事呢?

u-boot 中 有两个 all:目标的原因。
makefile 会以第一个目标作为默认目标,并且会被视为一个伪目标。在第一个all:之前有一段说明:

# Include autoconf.mk before config.mk so that the config options are available
# to all top level build files. We need the dummy all: target to prevent the
# dependency target in autoconf.mk.dep from being the default.


"前两句没什么好说的。关键是后一句:我们需要伪目标all:以防止autoconf.mk.dep中的目标成为默认目标。"
换句话说,如果这里不加上一个all:,则会产生一个结果,被包含进makefile中的autoconf.mk.dep中的第一个目标就有可能成为默认目标。这样,如果我们执行 make all,不会有什么问题。但只执行make,默认目标就不是all:目标了。
在一个makefile中,对于一个目标,可以多次重复的定义,可以多次定义其依赖,但只能定义一个目标动作,这样,可以利用条件执行对目标的依赖动态加载。
如 all: depend1
all: depend2
all:
command....
这样最终会先执行depend1然后depend2,最后去执行command...

为什么只能定义一个动作目标呢?

这与makefile相同目标的合并有关。

 target1: dep1

target1: dep2
           cmd2

这种情况下,这两个相同的target1会被合并成

 target1: dep1 dep2
         cmd2

 

但如果第一条规则本身也带一个命令的话, makefile就无法合并, 给出警告,并用后面的规则替代前面的规则

 target1: dep1
          cmd1
target1: dep2
           cmd2

 

最后生成的是, 其实就是后一条替代了前一条,然后给出警告

 target1: dep2
       cmd2
 
 
 
 

<2.1>加载autoconf.mk.dep和autoconf.mk 

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

 

如果程序找不到include的文件,make就会停止。
-include和sinclude作用一样,就是找不到你所包含的文件时不停止执行,忽略该错

 

<2.2>加载ARCH, BOARD和CPU配置,定义交叉编译器

# load ARCH, BOARD, and CPU configuration  //加载ARCH, BOARD和CPU配置
include $(obj)include/config.mk
export ARCH CPU BOARD VENDOR SOC

CROSS_COMPILE = arm-linux-

 

 包含 $(obj)/include/config.mk文件,我们知道在配置u-boot时,我们创建了include/config.mk并加载了ARCH, BOARD和CPU等有关参数。并定义交叉编译器 : arm -linux-

 

<2.3>设置默认没有本地构建

 # set default to nothing for native builds
ifeq ($(HOSTARCH),$(ARCH))
CROSS_COMPILE ?=
endif

 

HOSTARCH=i386     ARCH=arm,所以这里并不执行。

<2.4>加载其它配置

# load other configuration
include $(TOPDIR)/config.mk

 

加载顶层目录下的config.mk文件

<2.5>u-boot需要的目标文件(OBJS)和库文件(LIBS)。。。顺序很重要(i.e.start.o必须为第一个)

# U-Boot objects....order is important (i.e. start must be first)

OBJS  = cpu/$(CPU)/start.o
ifeq ($(CPU),i386)
OBJS += cpu/$(CPU)/start16.o
OBJS += cpu/$(CPU)/resetvec.o
endif
ifeq ($(CPU),ppc4xx)
OBJS += cpu/$(CPU)/resetvec.o
endif
ifeq ($(CPU),mpc85xx)
OBJS += cpu/$(CPU)/resetvec.o
endif

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

 

LIBS  = lib_generic/libgeneric.a
LIBS += lib_generic/lzma/liblzma.a
LIBS += lib_generic/lzo/liblzo.a
LIBS += $(shell if [ -f board/$(VENDOR)/common/Makefile ]; then echo \
 "board/$(VENDOR)/common/lib$(VENDOR).a"; fi)
LIBS += cpu/$(CPU)/lib$(CPU).a
ifdef SOC
LIBS += cpu/$(CPU)/$(SOC)/lib$(SOC).a
endif
ifeq ($(CPU),ixp)
LIBS += cpu/ixp/npe/libnpe.a
endif
LIBS += lib_$(ARCH)/lib$(ARCH).a
LIBS += fs/cramfs/libcramfs.a fs/fat/libfat.a fs/fdos/libfdos.a fs/jffs2/libjffs2.a \
 fs/reiserfs/libreiserfs.a fs/ext2/libext2fs.a fs/yaffs2/libyaffs2.a \
 fs/ubifs/libubifs.a
LIBS += net/libnet.a
LIBS += disk/libdisk.a
LIBS += drivers/bios_emulator/libatibiosemu.a
LIBS += drivers/block/libblock.a
LIBS += drivers/dma/libdma.a
LIBS += drivers/fpga/libfpga.a
LIBS += drivers/gpio/libgpio.a
LIBS += drivers/hwmon/libhwmon.a
LIBS += drivers/i2c/libi2c.a
LIBS += drivers/input/libinput.a
LIBS += drivers/misc/libmisc.a
LIBS += drivers/mmc/libmmc.a
LIBS += drivers/mtd/libmtd.a
LIBS += drivers/mtd/nand/libnand.a
LIBS += drivers/mtd/onenand/libonenand.a
LIBS += drivers/mtd/ubi/libubi.a
LIBS += drivers/mtd/spi/libspi_flash.a
LIBS += drivers/net/libnet.a
LIBS += drivers/net/phy/libphy.a
LIBS += drivers/pci/libpci.a
LIBS += drivers/pcmcia/libpcmcia.a
LIBS += drivers/power/libpower.a
LIBS += drivers/spi/libspi.a
ifeq ($(CPU),mpc83xx)
LIBS += drivers/qe/qe.a
endif
ifeq ($(CPU),mpc85xx)
LIBS += drivers/qe/qe.a
LIBS += cpu/mpc8xxx/ddr/libddr.a
LIBS += cpu/mpc8xxx/lib8xxx.a
endif
ifeq ($(CPU),mpc86xx)
LIBS += cpu/mpc8xxx/ddr/libddr.a
LIBS += cpu/mpc8xxx/lib8xxx.a
endif
LIBS += drivers/rtc/librtc.a
LIBS += drivers/serial/libserial.a
LIBS += drivers/twserial/libtws.a
LIBS += drivers/usb/gadget/libusb_gadget.a
LIBS += drivers/usb/host/libusb_host.a
LIBS += drivers/usb/musb/libusb_musb.a
 
# Apollo +
LIBS += drivers/usb/slave/libusb_slave.a
# Apollo -

LIBS += drivers/usb/phy/libusb_phy.a
LIBS += drivers/video/libvideo.a
LIBS += drivers/watchdog/libwatchdog.a
LIBS += common/libcommon.a
LIBS += libfdt/libfdt.a
LIBS += api/libapi.a
LIBS += post/libpost.a

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

 

LIBBOARD = board/$(BOARDDIR)/lib$(BOARD).a
LIBBOARD := $(addprefix $(obj),$(LIBBOARD))

$(addprefix prefix,names...)

参数‘names’作为一系列的文件名,文件名之间用空格隔开;prefix作为一个单位。将preffix(前缀)的值附加在每一个独立文件名的前面,完成后将文件名串联起来,它们之间用单个空格隔开。例如:

$(addprefix src/,foo bar)

结果为‘src/foo src/bar’。

 

 <2.6>添加gcc库

 ifdef USE_PRIVATE_LIBGCC
ifeq ("$(USE_PRIVATE_LIBGCC)", "yes")
PLATFORM_LIBGCC = -L $(OBJTREE)/lib_$(ARCH) -lgcc
else
PLATFORM_LIBGCC = -L $(USE_PRIVATE_LIBGCC) -lgcc
endif
else
PLATFORM_LIBGCC = -L $(shell dirname `$(CC) $(CFLAGS) -print-libgcc-file-name`) -lgcc
endif
PLATFORM_LIBS += $(PLATFORM_LIBGCC)
export PLATFORM_LIBS

1)USE_PRIVATE_LIBGCC = yes,从 /arch/arm/lib 中获得 libgcc.a

2)USE_PRIVATE_LIBGCC = path+file,从 指定的路径获得 libgcc.a

3)如果没有配置USE_PRIVATE_LIBGCC,就从工具链 libgcc路径获得。

 我们这里没有定义用户私有GCC库,所以执行ifdef的else分支

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

 CC和CFLAGS都是make的隐含变量,CC表示C语言编译器,缺省为:‘cc’。cflags表示执行CC时的命令行参数

 但是在这里并不是使用“cc”这个编译器,在顶层的config.mk文件中我们可以找到关于$(CC)和$(CFLAGS)的定义,如下:

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

CC = $(CROSS_COMPILE)gcc     //在Makefile中已经定义了:CROSS_COMPILE = arm-linux-

                                                        //所以这里:CC = arm-linux-gcc

 

 

u-boot编译(一)_第1张图片

 -print-libgcc-file-name :打印出所使用的编译器的libgcc.a文件的路径,例如:

u-boot编译(一)_第2张图片
 

dirname是输出已经去除了尾部“/”字符部分的名称(具体使用可以看这里),例如:

u-boot编译(一)_第3张图片
 

-L和-lgcc参数你可以man gcc一下
-L
表示:编译程序按照-L指定的路进去寻找库文件,一般的在-L的后面可以一次用-l指定多个库文件。

 

-lgcc 代表链接器将连接GCC的支持库libgcc.a  

 

<2.7>

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 = $(CROSS_COMPILE)ld      //arm-linux-ld

 

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

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

shell $(LD) –version表示取得连接工具的版本,我这里的版本号是:

 

u-boot编译(一)_第4张图片
 

 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 text, to, from)字符串替换函数,将$(obj)中的$(OBJS)置空

下面最终生成各种镜像文件,这里出现了我们用于下载的u-boot.bin 文件了。

 ALL += $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND) $(U_BOOT_ONENAND)

 all:  $(ALL)

$(obj)u-boot.hex: $(obj)u-boot
  $(OBJCOPY) ${OBJCFLAGS} -O ihex $< $@

$(obj)u-boot.srec: $(obj)u-boot
  $(OBJCOPY) -O srec $< $@

$(obj)u-boot.bin: $(obj)u-boot
  $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@

$(obj)u-boot.ldr: $(obj)u-boot
  $(CREATE_LDR_ENV)
  $(LDR) -T $(CONFIG_BFIN_CPU) -c $@ $< $(LDR_FLAGS)

$(obj)u-boot.ldr.hex: $(obj)u-boot.ldr
  $(OBJCOPY) ${OBJCFLAGS} -O ihex $< $@ -I binary

$(obj)u-boot.ldr.srec: $(obj)u-boot.ldr
  $(OBJCOPY) ${OBJCFLAGS} -O srec $< $@ -I binary

$(obj)u-boot.img: $(obj)u-boot.bin
  ./tools/mkimage -A $(ARCH) -T firmware -C none \
  -a $(TEXT_BASE) -e 0 \
  -n $(shell sed -n -e 's/.*U_BOOT_VERSION//p' $(VERSION_FILE) | \
   sed -e 's/"[  ]*$$/ for $(BOARD) board"/') \
  -d $< $@

$(obj)u-boot.imx:       $(obj)u-boot.bin
  $(obj)tools/mkimage -n $(IMX_CONFIG) -T imximage \
  -e $(TEXT_BASE) -d $< $@

$(obj)u-boot.kwb:       $(obj)u-boot.bin
  $(obj)tools/mkimage -n $(KWD_CONFIG) -T kwbimage \
  -a $(TEXT_BASE) -e $(TEXT_BASE) -d $< $@

$(obj)u-boot.sha1: $(obj)u-boot.bin
  $(obj)tools/ubsha1 $(obj)u-boot.bin

$(obj)u-boot.dis: $(obj)u-boot
  $(OBJDUMP) -d $< > $@

GEN_UBOOT = \
  UNDEF_SYM=`$(OBJDUMP) -x $(LIBBOARD) $(LIBS) | \
  sed  -n -e 's/.*\($(SYM_PREFIX)__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\
  cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) \
   --start-group $(__LIBS) --end-group $(PLATFORM_LIBS) \
   -Map u-boot.map -o u-boot
$(obj)u-boot: depend $(SUBDIRS) $(OBJS) $(LIBBOARD) $(LIBS) $(LDSCRIPT) $(obj)u-boot.lds
  $(GEN_UBOOT)

all依赖于$(ALL) 最终生成镜像文件,注意各种依赖关系。

重点分析一下“u-boot.bin”, u-boot.bin的依赖关系是这样的:$(obj)u-boot.bin   - >  $(obj)u-boot  - >

depend $(SUBDIRS) $(OBJS) $(LIBBOARD) $(LIBS) $(LDSCRIPT) $(obj)u-boot.lds

来看一下u-boot这个目标执行了哪些命令:

是$(GEN_UBOOT)这个变量,变量的内容是:

GEN_UBOOT = \
  UNDEF_SYM=`$(OBJDUMP) -x $(LIBBOARD) $(LIBS) | \
  sed  -n -e 's/.*\($(SYM_PREFIX)__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\
  cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) \
   --start-group $(__LIBS) --end-group $(PLATFORM_LIBS) \
   -Map u-boot.map -o u-boot

 

在目标目录下可以看到,经过编译之后多了下面这么几个文件;

u-boot编译(一)_第5张图片

 

到这里u-buut编译的前期工作基本差不多了,我们可以根据u-boot.bin的依赖关系,看看到底编译了哪些东西?

请看下一节“u-boot编译(二)”

 

 

 

 

 

实验(一)

在makefile中输入以下内容:


然后按下面的步骤执行 

你发现并不是你想象中顺序执行的结果:one  two  而实际是:two  two 。这就要我们读懂makefile的执行顺序了,在GNUmake使用手册,运行make一章中有讲到。我这里的更详细说明请看:makefile的运行顺序这一节。

你可能感兴趣的:(u-boot移植)