/*
Name:uboot之makefile分析
Data:2015-3-3
Author:suj_un
*/
Uboot之makefile分析
编译uboot,内核或者其他软件只需要执行make命令就可以生成可执行文件。执行命令后是怎么工作的?要知道这个就要看makefile了。现在就来揭开这玩意神秘的面纱。其中会粘一些代码段来分析。。。
VERSION = 2010
PATCHLEVEL = 03
SUBLEVEL =
EXTRAVERSION =
ifneq "$(SUBLEVEL)" ""
U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
else
U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL)$(EXTRAVERSION)
endif
TIMESTAMP_FILE = $(obj)include/timestamp_autogenerated.h
VERSION_FILE = $(obj)include/version_autogenerated.h
/******************前面这部分是定义boot的版本号的*******************/
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下执行uname -m,sed -e表示后面跟的是一串命令脚本,表达式s/axxx/bxxx表示从标准输入中查找内容为axxx并替换成bxxx,其中axxx中可以使用.作为通配符。*/
HOSTOS := $(shell uname -s | tr ‘[:upper:]‘ ‘[:lower:]‘ | \sed -e ‘s/\(cygwin\).*/cygwin/‘)
/* ******这句是获得开发主机的操作系统,和上面类似。tr ‘[:upper:]‘ ‘[:lower:]‘的作用是将标准输入中的所有大写字母转换成小写字母**********/
# 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)
/* 定义执行shell脚本的shell。若执行当前makefile的shell中定义了$BASH环境变量,并且文件"$BASH"是可执行文件,则SHELL的值为$BASH,否则若/bin/bash是可执行文件,SHELL的值为/bin/bash,否则SHELL的值为sh*/
exportHOSTARCH HOSTOS SHELL
/*********************************************************************************************************************/
ifdef O
ifeq ("$(origin O)", "command line")
BUILD_DIR := $(O)
endif
endif
/* 自定义编译输出目录, 函数$( origin, variable) 输出的结果是一个字符串,输出结果由变量variable定义的方式决定,若variable在命令行中定义过,则origin函数返回值为"command line"。则将BUILD_DIR设置为variable的值。假若在命令行中执行了“export BUILD_DIR=/tmp/build”的命令,则“$(origin O)”值为“command line”,而BUILD_DIR被设置为“/tmp/build”。*/
ifneq ($(BUILD_DIR),)
saved-output := $(BUILD_DIR)
# Attempt to create a output directory.
$(shell [ -d ${BUILD_DIR} ] || mkdir -p ${BUILD_DIR})
/**********若${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),)
/*************若${BUILD_DIR}为空,则将当前路径赋值给BUILD_DIR ****************/
ifeq ($(ARCH),arm)
CROSS_COMPILE = /opt/toolchains/arm-2009q3/bin/arm-linux-
endif
export CROSS_COMPILE
/***************定义交叉编译链的路径并配置到环境变量**************/
/* 后面一大段是定义源码路径和库文件的部分,省略*/
/*再接着就是编译依赖及可执行文件生成依赖部分,省略*/
itop_config:unconfig
@$(MKCONFIG) $(@:_config=) arm arm_cortexa9 smdkc210 samsung s5pc210
/* 自己开发板的配置 依赖unconfig 定义为:
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
它的作用是清除上次执行make *_config生成的配置文件(include/config.h,include/config.mk等)
下面那句$(@:_config=)的作用是将传进来的参数中的_config替换为空,因此此处得到itop。故这条命令分析实际为
./mkconfig itop arm arm_cortexa9 smdkc210 samsung s5pc210。因此执行mkconfig就得到了目标板型号,目标板cpu架构,cpu,板子号,生产厂家,SOC等信息
*/
接着看看mkconfig干了什么事
# Parameters: Target Architecture CPU Board [VENDOR] [SOC]
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
/*上来先进行参数检查,$#表示参数的个数此处为6,shift的作用是进行参数转换,即切换到下一个参数。进入循环判断参数中是否有--,-a等,我们的参数中没有故这段代码永远不会执行*/
[ "${BOARD_NAME}" ] || BOARD_NAME="$1"
[ $# -lt 4 ] && exit 1
[ $# -gt 6 ] && exit 1
/****BOARD_NAME的值设置为$1的值,在这里就是itop,判断参数的个数是否少于4个或者大于6个,如果成立则认为参数错误退出****/
下面就是对目标板的配置过程
再看看config.mk
前面一段是指定交叉编译命令
#Load generated board configuration
sinclude $(OBJTREE)/include/autoconf.mk
ifdef ARCH
sinclude $(TOPDIR)/lib_$(ARCH)/config.mk# include architecture dependend rules
endif
ifdef CPU
sinclude $(TOPDIR)/cpu/$(CPU)/config.mk# include CPUspecific rules
endif
ifdef SOC
sinclude $(TOPDIR)/cpu/$(CPU)/$(SOC)/config.mk# include SoCspecific rules
endif
ifdef VENDOR
BOARDDIR = $(VENDOR)/$(BOARD)
else
BOARDDIR = $(BOARD)
endif
ifdef BOARD
sinclude $(TOPDIR)/board/$(BOARDDIR)/config.mk# include board specific rules
endif
/*********这段是加载相应的config.mk文件。如果定义了相应的变量则加载对应路径下的文件,其中sinclude是如果后面路径中的文件存在则加载,如果不存在则什么事情都不干。*********/
至此makefile相关的东西基本就完了。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。