曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 6049|回复: 0
打印 上一主题 下一主题

Makefile 分析

[复制链接]

4917

主题

5879

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34382
跳转到指定楼层
楼主
发表于 2011-1-28 21:34:27 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
版本:1.2.0

VERSION =1
PATCHLEVEL =2
SUBLEVEL =0
EXTRAVERSION =
U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
VERSION_FILE = $(obj)include/version_autogenerated.h
定义了版本信息的相关变量。

HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \
sed -e 's/\(cygwin\).*/cygwin/')

export  HOSTARCH HOSTOS

# Deal with colliding definitions from tcsh etc.
VENDOR=
使用 uname -s 获得系统类型,后面用 tr 将大写字母([:upper:])转变为小写字母([:lower:]),比如 Linux 转换为 linux 。如果使用的是 cygwin ,那么名字就改为 cygwin 。这里需要提及一下,因为我基本上没用过 cygwin ,不知道在 cygwin 里使用 sed 时括号是不是需要转义后才能识别的,但在 linux 里,括号并不需要转义进行识别。

一段注释:
#########################################################################
#
# U-boot build supports producing a object files to the separate external
# directory. Two use cases are supported:
#U-boot 支持在不同的外部目录里存放编译产生的目标文件,有两种方式:
# 1) Add O= to the make command line
# 'make O=/tmp/build all'
# 可以在命令行里使用 O 参数来指定要存放的路径
# 2) Set environement variable BUILD_DIR to point to the desired location
# 'export BUILD_DIR=/tmp/build'
# 'make'
# 还可以在 Makefile 里设置环境变量 BUILD_DIR,使该变量指向要存放的路径
# The second approach can also be used with a MAKEALL script
# 'export BUILD_DIR=/tmp/build'
# './MAKEALL'
#
# Command line 'O=' setting overrides BUILD_DIR environent variable.
#
# When none of the above methods is used the local build is performed and
# the object files are placed in the source directory.
# 如果不用上面两种方法,那么 make 就在源码目录下执行,最后的目标文件也放在源码目录下
下面是对应注释的代码:
ifdef O
ifeq ("$(origin O)", "command line")
BUILD_DIR := $(O)
endif
endif
如果在命令行中使用 O 选项指定路径,那么就将命令行中给出的路径赋值到 BUILD_DIR 变量中,并且存往 save-output 变量中。

ifneq ($(BUILD_DIR),)
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),)
接着,若是已经指定了 BUILD_DIR 且当相应的目录不存在时,我们就手动建立它。最后,确认一下这个目录是否建立成功,确认方法是:
先 cd 到该目录,如果成功则用 pwd 获得该目录的路径,并把路径赋给 BUILD_DIR 变量。如果 BUILD_DIR 为空,那么就要用 error 函数停止 make 下去,程序退出。

OBJTREE         := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))
SRCTREE         := $(CURDIR)
TOPDIR          := $(SRCTREE)
LNDIR           := $(OBJTREE)
export  TOPDIR SRCTREE OBJTREE
上面,$(CURDIR) 是 Makefile 内置标准变量,表示当前 make 的路径。一般情况下,我们都很可能不会去指定 BUILD_DIR 路径,所以这里的结果是:$(OBJTREE) ,$(TOPDIR) 和 $(LNDIR) 都是一样的,都表示 u-boot 源码所在的顶层目录路径。

MKCONFIG        := $(SRCTREE)/mkconfig
export MKCONFIG
mkconfig 是一个脚本,这个脚本用来配置相关的环境信息。这里暂不展开对此脚本的分析。

ifneq ($(OBJTREE),$(SRCTREE))
REMOTE_BUILD    :=1
export REMOTE_BUILD
endif
从上面分析可知,一般情况下 $(OBJTREE) 等于 $(SRCTREE) ,所以此处的 REMOTE_BUILD 变量在后面也将不会用到。
# $(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
和上面的道理一样,这里的 obj 和 src 两个变量为空。

ifeq ($(OBJTREE)/include/config.mk,$(wildcard $(OBJTREE)/include/config.mk))

# load ARCH, BOARD, and CPU configuration
include $(OBJTREE)/include/config.mk
export  ARCH CPU BOARD VENDOR SOC
如果执行过诸如 make smdk2410_config 之类的配置命令之后,那么在 include/ 下就会生成 config.mk 文件,这个文件也就是由上面提到的 mkconfig 脚本生成的。比如 smdk2410 对应的 config.mk 文件的内容如下:
ARCH   = arm
CPU    = arm920t
BOARD  = smdk2410
SOC    = s3c24x0
ifndef CROSS_COMPILE
ifeq ($(HOSTARCH),ppc)
CROSS_COMPILE =
else
ifeq ($(ARCH),ppc)
CROSS_COMPILE =powerpc-linux-
endif
ifeq ($(ARCH),arm)
CROSS_COMPILE =arm-linux-
endif
... ... ... ...
export  CROSS_COMPILE
根据平台的不同,交叉编译器相应的变量 CROSS_COMPILE 也会不一样。正如 ARM 平台的 gcc 常见的名字为 arm-linux-gcc 。
# load other configuration
include $(TOPDIR)/config.mk
位于源码顶层目录下的 config.mk 是核心的 Makefile 文件,此时将它包含进来。

#########################################################################
# 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)/reset.o
endif
ifeq ($(CPU),ppc4xx)
OBJS += cpu/$(CPU)/resetvec.o
endif
ifeq ($(CPU),mpc85xx)
OBJS += cpu/$(CPU)/resetvec.o
endif
ifeq ($(CPU),mpc86xx)
OBJS += cpu/$(CPU)/resetvec.o
endif
ifeq ($(CPU),bf533)
OBJS += cpu/$(CPU)/start1.o     cpu/$(CPU)/interrupt.o  cpu/$(CPU)/cache.o
OBJS += cpu/$(CPU)/cplbhdlr.o   cpu/$(CPU)/cplbmgr.o    cpu/$(CPU)/flush.o
endif

OBJS := $(addprefix $(obj),$(OBJS))
一般的,OBJS 是由 cpu/$(CPU)/start.s 编译而来的目标文件  start.o。上面,像 i386, ppc4xx 等平台,它们的 OBJS 需要多个 *.o 文件。如果是 ARM 平台,那么只有一个 start.o 。start.s 是 bootloader 初始化 CPU 相关硬件第一个阶段代码文件(stage1)。

LIBS  = lib_generic/libgeneric.a
LIBS += board/$(BOARDDIR)/lib$(BOARD).a
LIBS += cpu/$(CPU)/lib$(CPU).a
ifdef SOC
LIBS += cpu/$(CPU)/$(SOC)/lib$(SOC).a
endif
LIBS += lib_$(ARCH)/lib$(ARCH).a
... ... ... ...
LIBS := $(addprefix $(obj),$(LIBS))
.PHONY : $(LIBS)
LIBS 表示相关的依赖库。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2024-5-7 11:19 , Processed in 0.076903 second(s), 22 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表