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

 

 

2.u-boot編譯(一)

 -print-libgcc-file-name :打印出所使用的編譯器的libgcc.a文件的路徑,例如:

2.u-boot編譯(一)
 

dirname是輸出已經去除了尾部“/”字符部分的名稱(具體使用可以看這裏),例如:

2.u-boot編譯(一)
 

-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表示取得連接工具的版本,我這裏的版本號是:

 

2.u-boot編譯(一)
 

 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

 

在目標目錄下可以看到,經過編譯之後多了下面這麼幾個文件;

2.u-boot編譯(一)

 

到這裏u-buut編譯的前期工作基本差不多了,我們可以根據u-boot.bin的依賴關係,看看到底編譯了哪些東西?

請看下一節“u-boot編譯(二)”

 

 

 

 

 

實驗(一)

在makefile中輸入以下內容:


然後按下面的步驟執行 

你發現並不是你想象中順序執行的結果:one  two  而實際是:two  two 。這就要我們讀懂makefile的執行順序了,在GNUmake使用手冊,運行make一章中有講到。我這裏的更詳細說明請看:makefile的運行順序這一節。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章