Article directory
- U-boot Makefile national construction process
- Host build environment configuration process
- Define host system architecture
- Define host operating system type
- Define SHELL script interpreter
- Set compile output directory
- Configuration process related to target machine
- mkconfig script
- Pass to mkconfig script parameter
- Check the validity of parameters
- Create a link to a catalog board related catalog
- Build 'include/config.mk' file
- Build 'include/config.h' file
- make command execution process
- Top level directory 'config,mk' analysis
U-boot Makefile national construction process
Host build environment configuration process
Define host system architecture
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) is the statement after the shell, which is executed according to the shell script.
sed -e s/in/out / is to replace the input in with out
Running example:
andrew@andrew-Thurley:~/work/test$ uname -m x86_64 # . is a single character wildcard andrew@andrew-Thurley:~/work/test$ uname -m |sed -e s/x86.64/x86/ x86
Define host operating system type
HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \ sed -e 's/\(cygwin\).*/cygwin/')
TR '[: Upper:]' [: lower:] 'is used to convert all uppercase letters in standard input to lowercase letters
Execution example
andrew@andrew-Thurley:~/work/test$ uname -s | tr '[:upper:]' '[:lower:]' | sed -e 's/\(cygwin\).*/cygwin/' linux
Define SHELL script interpreter
The Makefile at the top of uboot defines shell, the interpreter of shell script, through the following code. The function of "$BASH" is essentially to generate the string "BASH", which is essentially to generate the string "BASH". The function of the previous $is to show that the second $is a common character.
# 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)
The function of the above script is that if $BASH environment variable is defined in the shell of the current Makefile, and the file $BASH is executable, the value of shell is "$BASH". If / bin/bash is executable, the value of shell is "/ bin/bash". If neither of the above is true, assign sh to the shell variable.
Set compile output directory
ifdef O ifeq ("$(origin O)", "command line") BUILD_DIR := $(O) endif endif
$(origin O) indicates the output of the (origin O) function. The output of $(origin variable) is a string, which is determined by the way variable is defined. If variable is a parameter of make, $(origin variable) outputs the common line string.
The effect of the above method is make O=/tmp/buildall, because O is the parameter of make, so $(origin variable) outputs common line, and BUILD_DIR is / tmp/buildall.
The next configuration is as follows:
ifneq ($(BUILD_DIR),) #If the directory exists, assign the directory to saved output saved-output := $(BUILD_DIR) # Attempt to create a output directory. # Directory exists and then executes, directory does not exist create directory $(shell [ -d ${BUILD_DIR} ] || mkdir -p ${BUILD_DIR}) # Verify if it was successful. # Make sure the directory exists BUILD_DIR := $(shell cd $(BUILD_DIR) && /bin/pwd) # Check the catalog $(if $(BUILD_DIR),,$(error output directory "$(saved-output)" does not exist)) endif # ifneq ($(BUILD_DIR),)
CURDIR represents the current directory
If OBJTREE does not define build dir, the output directory is CURDIR, that is, the place where make is executed. That is, when make is executed without a specified directory, the u-boot generated will be on the top directory.
$(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR)) if BUILD_DIR exists, BUILD_DIR will be used; if no share exists, CURDIR will be used.
OBJTREE := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR)) SRCTREE := $(CURDIR) TOPDIR := $(SRCTREE) LNDIR := $(OBJTREE) export TOPDIR SRCTREE OBJTREE MKCONFIG := $(SRCTREE)/mkconfig export MKCONFIG ifneq ($(OBJTREE),$(SRCTREE)) REMOTE_BUILD := 1 export REMOTE_BUILD endif
Define obj and Src variables before including config.mk, and put them into the environment temporarily.
export obj src
# $(obj) and (src) are defined in config.mk but here in main Makefile # we also need them before config.mk is included which is the case for # some targets like unconfig, clean, clobber, distclean, etc. ifneq ($(OBJTREE),$(SRCTREE)) obj := $(OBJTREE)/ src := $(SRCTREE)/ else obj := src := endif export obj src
Configuration process related to target machine
There are configurations related to the specific development board in the top-level Makefile. The @ function does not show that obj is the directory of the compiled output when executing the command. Therefore, the unconfig function is to know the configuration file generated by the last execution of the make * * config command.
$(@: _config =) replaces_config of all the parameters passed in with null, where @ refers to the target of the rule, using the syntax of @ (text:patternA=patternB), replacing all text ending in patternA with patternB, so the function of $(@: _config =) is to remove_config after smdk2410_config to get smdk2410
The final effect is equivalent to:
@$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 samsung s3c24x0
==>
./mkconfig smdk2410 arm arm920t smdk2410 samsung s3c24x0
This method is given in mkconfig
# Parameters: Target Architecture CPU Board [VENDOR] [SOC]
unconfig: @rm -f $(obj)include/config.h $(obj)include/config.mk \ $(obj)board/*/config.tmp $(obj)board/*/*/config.tmp \ $(obj)include/autoconf.mk $(obj)include/autoconf.mk.dep smdk2410_config : unconfig @$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 samsung s3c24x0
mkconfig script
Pass to mkconfig script parameter
The meaning passed to the mkconfig script is as follows:
- Smdk2410, target (model of target board)
- Arm, architecture (CPU architecture of target board)
- ARM920T, CPU (specific CPU model used by CPU)
- smdk2410, development board name
- samsung,VENDOR manufacturer name
- S3c24x0, SOC (system on chip)
Where the environment variable $ා represents the number of parameters passed to the script.
The function of shift is that the original parameter $1 will be lost, and the later parameter will be shifted forward.
APPEND=no # Default: Create new config file BOARD_NAME="" # Name to print in make output TARGETS="" while [ $# -gt 0 ] ; do case "$1" in --) shift ; break ;; -a) shift ; APPEND=yes ;; -n) shift ; BOARD_NAME="${1%%_config}" ; shift ;; -t) shift ; TARGETS="`echo $1 | sed 's:_: :g'` ${TARGETS}" ; shift ;; *) break ;; esac done [ "${BOARD_NAME}" ] || BOARD_NAME="$1"
After the execution of the above code, BOARD_NAME = smdk2410, because the mkconfig execution statement of the top-level Makefile construction is:. / mkconfig smdk2410 arm ARM920T smdk2410 sampling s3c24x0
Check the validity of parameters
The following code is used to check the validity of parameters. If the number of parameters is less than 4 or more than 6, it will be considered illegal.
[ $# -lt 4 ] && exit 1 [ $# -gt 6 ] && exit 1 if [ "${ARCH}" -a "${ARCH}" != "$2" ]; then echo "Failed: \$ARCH=${ARCH}, should be '$2' for ${BOARD_NAME}" 1>&2 exit 1 fi
Create a link to a catalog board related catalog
If compile output to external directory, the following code game oh.
When the "$srctree"! = "$objtree" condition is set, the output external directory is defined.
# # Create link to architecture specific headers # if [ "$SRCTREE" != "$OBJTREE" ] ; then mkdir -p ${OBJTREE}/include mkdir -p ${OBJTREE}/include2 cd ${OBJTREE}/include2 rm -f asm ln -s ${SRCTREE}/include/asm-$2 asm LNPREFIX="../../include2/asm/" cd ../include rm -rf asm-$2 rm -f asm mkdir asm-$2 ln -s asm-$2 asm
If the target file is set to output to the directory where the source file is located, a symbolic connection is established to the ASM arm directory under the include directory in the top directory. The code is as follows: ln -s asm-, asm, that is, LN - s ASM arm ASM
else cd ./include rm -f asm ln -s asm-$2 asm fi
The script then establishes the symbolic link include / ASM arm / arch through the following code. If & 6 (SOC) is empty, it will link to the directory include / ASM arm / arch-arm920t. Otherwise, it will link to the directory include / ASM arm / arch-s3cx0. In fact, the directory include / ASM arm / arch-arm920t does not exist, so the sixth parameter must be filled in. Otherwise, the compilation will fail.
rm -f asm-$2/arch if [ -z "$6" -o "$6" = "NULL" ] ; then ln -s ${LNPREFIX}arch-$3 asm-$2/arch else ln -s ${LNPREFIX}arch-$6 asm-$2/arch fi
The development board is an arm based proc linked to proc armv.
if [ "$2" = "arm" ] ; then rm -f asm-$2/proc ln -s ${LNPREFIX}proc-armv asm-$2/proc fi
Build the include/config.mk file
# # 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
What the above code implements
ARCH = arm CPU = arm920t BOARD = smdk2410 VENDOR = samsung SOC = s3c24x0
Build the include/config.h file
# # Create board specific header file # if [ "$APPEND" = "yes" ] # Append to existing config file then echo >> config.h #Add a enter key else > config.h # Create new config file fi echo "/* Automatically generated - do not edit */" >>config.h for i in ${TARGETS} ; do echo "#define CONFIG_MK_${i} 1" >>config.h ; done echo "#include <configs/$1.h>" >>config.h echo "#include <asm/config.h>" >>config.h exit 0
make command execution process
After making clear the construction environment of the host and the related configuration of the target machine, the following analyzes the process of executing the make command and finally generating the u-boot image.
Normal execution of make smdk2410 ﹐ config will enter the directory of ifeq.
If the environment of the host and the development board is the same, the host compiler is used, and the cross compilation tool definition is empty.
# set default to nothing for native builds ifeq ($(HOSTARCH),$(ARCH)) CROSS_COMPILE ?= endif
Next, it contains config.mk under the top-level directory.
# 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 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/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.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 $(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.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))' ) > $@.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 1 updater: $(MAKE) -C tools/updater all || exit 1 env: $(MAKE) -C tools/env all MTD_VERSION=${MTD_VERSION} || exit 1 depend dep: $(TIMESTAMP_FILE) $(VERSION_FILE) $(obj)include/autoconf.mk for dir in $(SUBDIRS) ; do $(MAKE) -C $$dir _depend ; done TAG_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/video tags 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.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 > $@.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
Top level directory config,mk analysis
Set compilation options
# clean the slate ... PLATFORM_RELFLAGS = PLATFORM_CPPFLAGS = PLATFORM_LDFLAGS =
Check if the compiler supports function definitions for certain options
######################################################################### # # 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 ;)
Function usage
You can call the CC option function to this
GFLAGS += $(call cc-option, option1, option2)
CFLAGS += $(call cc-option,-fno-stack-protector)
Perform cross compilation tool
# # 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
For the arm development board, cross figure in the above code is defined in lib arm / config.mk
CROSS_COMPILE ?= arm-linux-
Contains configuration files related to the development board
In the following code, the value of $(ARCH) is "arm", so include lib_arm/config.mk
# Load generated board configuration sinclude $(OBJTREE)/include/autoconf.mk ifdef ARCH sinclude $(TOPDIR)/lib_$(ARCH)/config.mk # include architecture dependend rules endif
The function of dependency is to generate dependency. Executing this command will enter the subdirectory represented by $(subirs) once, and execute the make ﹐ dependent command to generate. Dependency files in each subdirectory, and list the dependency files of each target file in the. Dependent file.
$(obj)u-boot: depend $(SUBDIRS) $(OBJS) $(LIBBOARD) $(LIBS) $(LDSCRIPT) $(obj)u-boot.lds $(GEN_UBOOT)
u-boot.lds file
# Specify that the output executable is 32-bit ARM instruction, ELF format of small end mode OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") # Specify the output executable platform as ARM OUTPUT_ARCH(arm) # Specify the entry of the program as "start" ENTRY(_start) SECTIONS { # Specifies the starting address of the target code from 0x00, "." represents the current location . = 0x00000000; # Mark 4-byte alignment . = ALIGN(4); .text : { # Indicates that start.o is the first. o file in the code snippet cpu/arm920t/start.o (.text) # The rest of the code snippet *(.text) } . = ALIGN(4); .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } . = ALIGN(4); # Data segment .data : { *(.data) } . = ALIGN(4); .got : { *(.got) } . = .; __u_boot_cmd_start = .; .u_boot_cmd : { *(.u_boot_cmd) } __u_boot_cmd_end = .; . = ALIGN(4); # __The bss_start label points to the start of the BSS segment __bss_start = .; # Here is a piece of memory in the bss section to store the bit initialization variables in the program. .bss (NOLOAD) : { *(.bss) . = ALIGN(4); } _end = .; }