u-boot编译过程分析
文章目錄
- U-boot Makefile國建過程
- 主機構建環境配置過程
- 定義主機系統架構
- 定義主機操作系統類型
- 定義SHELL腳本的解釋器
- 設定編譯輸出目錄
- 目標機相關配置過程
- mkconfig腳本
- 傳遞給mkconfig腳本參數
- 檢查參數合法性
- 創建到目錄板相關目錄的鏈接
- 構建`include/config.mk`文件
- 構建`include/config.h`文件
- make命令執行過程
- 頂層目錄`config,mk`分析
- 包含與開發板相關的配置文件
- `u-boot.lds`文件
U-boot Makefile國建過程
主機構建環境配置過程
定義主機系統架構
HOSTARCH := $(shell uname -m | \sed -e s/i.86/i386/ \-e s/sun4u/sparc64/ \-e s/arm.*/arm/ \-e s/sa110/arm/ \-e s/powerpc/ppc/ \-e s/ppc64/ppc/ \-e s/macppc/ppc/)$(shell xxx)是shell后面的語句,按照shell腳本進行執行
sed -e s/in/out/是將輸入的in替換成out
運行示例:
andrew@andrew-Thurley:~/work/test$ uname -m x86_64 # .為單個字符的通配符 andrew@andrew-Thurley:~/work/test$ uname -m |sed -e s/x86.64/x86/ x86定義主機操作系統類型
HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \sed -e 's/\(cygwin\).*/cygwin/')tr '[:upper:]' '[:lower:]'的作用是將標準輸入中的所有大寫字母轉換為小寫字母
執行示例
andrew@andrew-Thurley:~/work/test$ uname -s | tr '[:upper:]' '[:lower:]' | sed -e 's/\(cygwin\).*/cygwin/' linux定義SHELL腳本的解釋器
uboot頂層的Makefile通過如下代碼定義了shell腳本的解釋器SHELL。"$BASH"的作用實質上是生成字符串"BASH"的作用實質上是生成字符串"BASH"的作用實質上是生成字符串"BASH" ,前一個$的作用是說明第二個$是普通字符。
# Set shell to bash if possible, otherwise fall back to sh SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \else if [ -x /bin/bash ]; then echo /bin/bash; \else echo sh; fi; fi)上述腳本的作用為,若當前Makefile的shell中定義了$BASH環境變量,且文件$BASH是可執行文件,則SHELL的值為”$BASH“,若/bin/bash是可執行文件,則SHELL的值為"/bin/bash"。若以上兩者都不成立,將sh賦值給SHELL變量。
設定編譯輸出目錄
ifdef O ifeq ("$(origin O)", "command line") BUILD_DIR := $(O) endif endif$(origin O)表示,(origin O)函數的輸出,$(origin variable)的輸出是結果是一個字符串,由變量variable定義的方式決定,若variable是作為make的參數時,$(origin variable)輸出commond line字符串。
以上方式實現的效果為 make O=/tmp/buildall, 因為,O作為make的參數,所以$(origin variable)輸出commond line, BUILD_DIR為/tmp/buildall。
接下來的配置如下:
ifneq ($(BUILD_DIR),) #如果目錄存在,就將目錄賦值給saved-output saved-output := $(BUILD_DIR)# Attempt to create a output directory. # 目錄存在接著執行,目錄不存在創建目錄 $(shell [ -d ${BUILD_DIR} ] || mkdir -p ${BUILD_DIR})# Verify if it was successful. # 確保目錄存在 BUILD_DIR := $(shell cd $(BUILD_DIR) && /bin/pwd) # 對目錄進行檢測 $(if $(BUILD_DIR),,$(error output directory "$(saved-output)" does not exist)) endif # ifneq ($(BUILD_DIR),)CURDIR表示的是當前目錄
OBJTREE 若是沒有定義BUILD_DIR,則輸出目錄就是CURDIR,也就是執行make的地方,這就是執行make沒有指定目錄的時候生成的u-boot會在頂層目錄上。
$(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))如果第BUILD_DIR存在就BUILD_DIR,入股不存在就使用CURDIR
在沒有包含config.mk之前先將obj,src變量定義好,并臨時放到環境中
export obj src
目標機相關配置過程
頂層Makefile存在與具體開發板的相關配置,其中@的作用就執行該命令時不顯示obj是編譯輸出的目錄,因此unconfig的作用就是清楚上次執行make *_config命令生成的配置文件。
$(@:_config=)將傳進來的所有參數的_config替換為空,其中@是指規則的目標,使用的語法為@(text:patternA=patternB)這樣的語法,將text中所有以patternA結尾的文本替換為patternB,因此$(@:_config=)的作用是將smdk2410_config后面的_config去掉,得到smdk2410
最終的效果相當于:
@$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 samsung s3c24x0
==>
./mkconfig smdk2410 arm arm920t smdk2410 samsung s3c24x0
這種使用方法在mkconfig中有給出
# Parameters: Target Architecture CPU Board [VENDOR] [SOC]
mkconfig腳本
傳遞給mkconfig腳本參數
傳遞給mkconfig腳本的含義如下:
- smdk2410, Target(目標板的型號)
- arm, Architecture(目標板的CPU架構)
- arm920t, CPU(CPU使用的具體CPU型號)
- smdk2410,開發板名稱
- samsung,VENDOR生產廠家名稱
- s3c24x0,SOC(片上系統)
其中環境變量$#表示傳遞給腳本的的參數的個數,
shift的作用是原來的參數$1將丟失,并將后面的參數向前進行平移,
上述代碼執行結束之后 BOARD_NAME = smdk2410,因為頂層Makefile構造的mkconfig執行語句為 :./mkconfig smdk2410 arm arm920t smdk2410 samsung s3c24x0
檢查參數合法性
下面的代碼用于檢查參數的合法性,參數的個數少于4個和多于6個都將認為是不合法的
[ $# -lt 4 ] && exit 1 [ $# -gt 6 ] && exit 1if [ "${ARCH}" -a "${ARCH}" != "$2" ]; thenecho "Failed: \$ARCH=${ARCH}, should be '$2' for ${BOARD_NAME}" 1>&2exit 1 fi創建到目錄板相關目錄的鏈接
若編譯輸出到外部目錄,則下面代碼游戲哦啊。
"$SRCTREE" != "$OBJTREE"條件成立的時候,就是外部定義了輸出外部目錄的時候
若將目標文件設定為輸出到源文件所在目錄,就在頂層目錄中的include目錄下建立到asm-arm目錄的符號連接,代碼如下,其中的ln -s asm-$2 asm即 ln -s asm-arm asm
elsecd ./includerm -f asmln -s asm-$2 asm fi緊接著該腳本通過下面的代碼建立符號鏈接include/asm-arm/arch,若&6(SOC)為空,則其鏈接到include/asm-arm/arch-arm920t目錄,否則使其鏈接到include/asm-arm/arch-s3cx0目錄,事實上include/asm-arm/arch-arm920t并不存在,因此第六個參數必須填寫。,否則會編譯失效。
rm -f asm-$2/archif [ -z "$6" -o "$6" = "NULL" ] ; thenln -s ${LNPREFIX}arch-$3 asm-$2/arch elseln -s ${LNPREFIX}arch-$6 asm-$2/arch fi開發板是arm架構 proc鏈接到proc-armv下。
if [ "$2" = "arm" ] ; thenrm -f asm-$2/procln -s ${LNPREFIX}proc-armv asm-$2/proc fi構建include/config.mk文件
# # Create include file for Make # echo "ARCH = $2" > config.mk echo "CPU = $3" >> config.mk echo "BOARD = $4" >> config.mk[ "$5" ] && [ "$5" != "NULL" ] && echo "VENDOR = $5" >> config.mk[ "$6" ] && [ "$6" != "NULL" ] && echo "SOC = $6" >> config.mk上面代碼實現的內容
ARCH = arm CPU = arm920t BOARD = smdk2410 VENDOR = samsung SOC = s3c24x0構建include/config.h文件
# # Create board specific header file # if [ "$APPEND" = "yes" ] # Append to existing config file thenecho >> config.h #加個回車鍵 else> config.h # Create new config file fi echo "/* Automatically generated - do not edit */" >>config.hfor i in ${TARGETS} ; doecho "#define CONFIG_MK_${i} 1" >>config.h ; doneecho "#include <configs/$1.h>" >>config.h echo "#include <asm/config.h>" >>config.hexit 0make命令執行過程
在搞清楚主機的構建環境和目標機相關配置之后,下面來分析執行make命令并最終生成u-boot鏡像的過程。
正常的執行make smdk2410_config時會進入到ifeq的目錄。
若主機和開發板的環境一樣,則使用主機編譯器,交叉編譯工具定義為空
# set default to nothing for native builds ifeq ($(HOSTARCH),$(ARCH)) CROSS_COMPILE ?= endif緊接著包含頂層目錄下的config.mk
# load other configuration include $(TOPDIR)/config.mk # The "tools" are needed early, so put this first # Don't include stuff already done in $(LIBS) SUBDIRS = tools \examples/standalone \examples/api.PHONY : $(SUBDIRS)ifeq ($(obj)include/config.mk,$(wildcard $(obj)include/config.mk))# 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: 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# 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 endifOBJS := $(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/net/sk98lin/libsk98lin.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 TAG_SUBDIRS += cpu/mpc8xxx endif ifeq ($(CPU),mpc86xx) LIBS += cpu/mpc8xxx/ddr/libddr.a LIBS += cpu/mpc8xxx/lib8xxx.a TAG_SUBDIRS += cpu/mpc8xxx 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 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.aLIBS := $(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 endififeq ($(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$(obj)tools/envcrc --binary > $(obj)env-ldr.o$(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.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.bincat $(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.bincat $(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))' ) > $@.tmp@cmp -s $@ $@.tmp && rm -f $@.tmp || mv -f $@.tmp $@$(TIMESTAMP_FILE):@date +'#define U_BOOT_DATE "%b %d %C%y"' > $@@date +'#define U_BOOT_TIME "%T"' >> $@gdbtools:$(MAKE) -C tools/gdb all || exit 1updater:$(MAKE) -C tools/updater all || exit 1env:$(MAKE) -C tools/env all MTD_VERSION=${MTD_VERSION} || exit 1depend dep: $(TIMESTAMP_FILE) $(VERSION_FILE) $(obj)include/autoconf.mkfor dir in $(SUBDIRS) ; do $(MAKE) -C $$dir _depend ; doneTAG_SUBDIRS += include TAG_SUBDIRS += lib_generic board/$(BOARDDIR) TAG_SUBDIRS += cpu/$(CPU) TAG_SUBDIRS += lib_$(ARCH) TAG_SUBDIRS += fs/cramfs TAG_SUBDIRS += fs/fat TAG_SUBDIRS += fs/fdos TAG_SUBDIRS += fs/jffs2 TAG_SUBDIRS += fs/yaffs2 TAG_SUBDIRS += net TAG_SUBDIRS += disk TAG_SUBDIRS += common TAG_SUBDIRS += drivers/bios_emulator TAG_SUBDIRS += drivers/block TAG_SUBDIRS += drivers/gpio TAG_SUBDIRS += drivers/hwmon TAG_SUBDIRS += drivers/i2c TAG_SUBDIRS += drivers/input TAG_SUBDIRS += drivers/misc TAG_SUBDIRS += drivers/mmc TAG_SUBDIRS += drivers/mtd TAG_SUBDIRS += drivers/mtd/nand TAG_SUBDIRS += drivers/mtd/onenand TAG_SUBDIRS += drivers/mtd/spi TAG_SUBDIRS += drivers/net TAG_SUBDIRS += drivers/net/sk98lin TAG_SUBDIRS += drivers/pci TAG_SUBDIRS += drivers/pcmcia TAG_SUBDIRS += drivers/qe TAG_SUBDIRS += drivers/rtc TAG_SUBDIRS += drivers/serial TAG_SUBDIRS += drivers/spi TAG_SUBDIRS += drivers/usb TAG_SUBDIRS += drivers/videotags ctags:ctags -w -o $(obj)ctags `find $(SUBDIRS) $(TAG_SUBDIRS) \-name '*.[ch]' -print`etags:etags -a -o $(obj)etags `find $(SUBDIRS) $(TAG_SUBDIRS) \-name '*.[ch]' -print` cscope:find $(SUBDIRS) $(TAG_SUBDIRS) -name '*.[ch]' -print \> cscope.filescscope -b -q -kSYSTEM_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 > $@.tmp && \mv $@.tmp $@######################################################################### 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 \ $(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 endif # config.mk頂層目錄config,mk分析
設置編譯選項
# clean the slate ... PLATFORM_RELFLAGS = PLATFORM_CPPFLAGS = PLATFORM_LDFLAGS =檢查編譯器是否支持某些選項的函數定義
######################################################################### # # Option checker (courtesy linux kernel) to ensure # only supported compiler options are used # cc-option = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \> /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)函數使用
可以向這樣調用cc-option函數
GFLAGS += $(call cc-option, option1, option2)
執行交叉編譯工具
# # Include the make variables (CC, etc...) # AS = $(CROSS_COMPILE)as LD = $(CROSS_COMPILE)ld 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 RANLIB = $(CROSS_COMPILE)RANLIB對于arm開發板,上面代碼中的CROSS_COMPILE在lib_arm/config.mk中定義
CROSS_COMPILE ?= arm-linux-
包含與開發板相關的配置文件
在下面的代碼中,$(ARCH)的值為"arm",因此將lib_arm/config.mk包含進來
# Load generated board configuration sinclude $(OBJTREE)/include/autoconf.mkifdef ARCH sinclude $(TOPDIR)/lib_$(ARCH)/config.mk # include architecture dependend rules endifdepend的作用是,生成depend依賴,執行該命令將一次進入$(SUBDIRS)表示的子目錄中,并執行,make _depend命令,生成各個子目錄中的.depend文件,在.depend文件中列出每個目標文件的依賴文件
$(obj)u-boot: depend $(SUBDIRS) $(OBJS) $(LIBBOARD) $(LIBS) $(LDSCRIPT) $(obj)u-boot.lds$(GEN_UBOOT)u-boot.lds文件
# 指定輸出的可執行文件是32位的ARM指令,小端模式的ELF格式 OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") # 指定輸出可執行平臺為ARM OUTPUT_ARCH(arm)# 指定程序的入口為_start ENTRY(_start) SECTIONS {# 指定目標代碼的起始地址從0x00開始,"."代表當前位置. = 0x00000000;# 標示4字節對齊. = ALIGN(4);.text :{# 表明 start.o是代碼段的第一個.o文件cpu/arm920t/start.o (.text)# 代碼段的其余部分*(.text)}. = ALIGN(4);.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }. = ALIGN(4);# 數據段.data : { *(.data) }. = ALIGN(4);.got : { *(.got) }. = .;__u_boot_cmd_start = .;.u_boot_cmd : { *(.u_boot_cmd) }__u_boot_cmd_end = .;. = ALIGN(4);# __bss_start 標號指向bss段的開始位置__bss_start = .;# 這里是bss段 存放程序中位初始化變量的一塊內存.bss (NOLOAD) : { *(.bss) . = ALIGN(4); }_end = .; }總結
以上是生活随笔為你收集整理的u-boot编译过程分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 作者:那旭(1990-),女,中国医学
- 下一篇: 作者:朱艳华(1982-),女,中国科学