zoukankan      html  css  js  c++  java
  • uboot主Makefile分析

    VERSION = 1
    PATCHLEVEL = 3
    SUBLEVEL = 4
    EXTRAVERSION =
    U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
    VERSION_FILE = $(obj)include/version_autogenerated.h

    (1)uboot的版本号分3个级别:
    VERSION:主板本号
    PATCHLEVEL:次版本号
    SUBLEVEL:再次版本号
    EXTRAVERSION:另外附加的版本信息
    这4个用.分隔开共同构成了最终的版本号。
    (2)Makefile中版本号最终生成了一个变量U_BOOT_VERSION,这个变量记录了Makefile中配置的版本号。
    (3)include/version_autogenerated.h文件是编译过程中自动生成的一个文件,所以源目录中没有,但是编译过后的uboot中就有了。它里面的内容是一个宏定义,宏定义的值内容就是我们在Makefile中配置的uboot的版本号。

    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/)
    
    HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | 
    	    sed -e 's/(cygwin).*/cygwin/')
    
    export	HOSTARCH HOSTOS
    

      

    (1)直接在shell中执行uname -m得到i686,得到的值其实你当前执行这个命令的电脑的CPU的版本号。
    (2)shell中的|叫做管道,管道的作用就是把管道前面一个运算式的输出作为后面一个的输入再去做处理,最终的输出才是我们整个式子的输出。
    (3)HOSTARCH这个名字:HOST是主机,就是当前在做开发用的这台电脑就叫主机;ARCH是architecture(架构)的缩写,表示CPU的架构。所以HOSTARCH就表示主机的CPU的架构。
    (4)这两个环境变量是主机的操作系统和主机的CPU架构,得出后保存备用,后面自然会用到。

    #########################################################################
    # Allow for silent builds
    ifeq (,$(findstring s,$(MAKEFLAGS)))
    XECHO = echo
    else
    XECHO = :
    endif
    
    #########################################################################
    

      静默编译

    (1)平时默认编译时命令行会打印出来很多编译信息。但是有时候我们不希望看到这些编译信息,就后台编译即可。这就叫静默编译。
    (2)使用方法就是编译时make -s,-s会作为MAKEFLAGS传给Makefile,在上面这段代码作用下XECHO变量就会被变成空(默认等于echo),于是实现了静默编译。

    ifdef O
    ifeq ("$(origin O)", "command line")
    BUILD_DIR := $(O)
    endif
    endif
    
    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),)
    
    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
    
    # $(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
    
    # Make sure CDPATH settings don't interfere
    unexport CDPATH
    

      

    2种编译方法(原地编译和单独输出文件夹编译)
    (1)编译复杂项目,Makefile提供2种编译管理方法。默认情况下是当前文件夹中的.c文件,编译出来的.o文件会放在同一文件夹下。这种方式叫原地编译。原地编译的好处就是处理起来简单。
    (2)原地编译有一些坏处:第一,污染了源文件目录。第二的缺陷就是一套源代码只能按照一种配置和编译方法进行处理,无法同时维护2个或2个以上的配置编译方式。
    (3)为了解决以上2种缺陷,uboot支持单独输出文件夹方式的编译(linux kernel也支持,而且uboot的这种技术就是从linux kernel学习来的)。基本思路就是在编译时另外指定一个输出目录,将来所有的编译生成的.o文件或生成的其他文件全部丢到那个输出目录下去。源代码目录不做任何污染,这样输出目录就承载了本次配置编译的所有结果。
    (4)具体用法:默认的就是原地编译。如果需要指定具体的输出目录编译则有2种方式来指定输出目录。(具体参考Makefile 56-76行注释内容)
    第一种:make O=输出目录
    第二种:export BUILD_DIR=输出目录 然后再make
    如果两个都指定了(既有BUILD_DIR环境变量存在,又有O=xx),则O=xx具有更高优先级,听他的。
    (5)两种编译的实现代码在Makefile的实现方法为上面代码。

    OBJTREE、SRCTREE、TOPDIR
    (1)OBJTREE:编译出的.o文件存放的目录的根目录。在默认编译下,OBJTREE等于当前目录;在O=xx编译下,OBJTREE就等于我们设置的那个输出目录。
    (2)SRCTREE: 源码目录,其实就是源代码的根目录,也就是当前目录。
    总结:在默认编译下,OBJTREE和SRCTREE相等;在O=xx这种编译下OBJTREE和SRCTREE不相等。Makefile中定义这两个变量,其实就是为了记录编译后的.o文件往哪里放,就是为了实现O=xx的这种编译方式的。

    MKCONFIG	:= $(SRCTREE)/mkconfig
    

      Makefile中定义的一个变量(在这里定义,在后面使用),它的值就是我们源码根目录下面的mkconfig。这个mkconfig是一个脚本,这个脚本就是uboot配置阶段的配置脚本。后面要用至少3节课详细讲这个配置脚本的工作。

    include $(obj)include/config.mk
    export	ARCH CPU BOARD VENDOR SOC
    

      

    1)include/config.mk不是源码自带的(你在没有编译过的源码目录下是找不到这个文件的),要在配置过程(make x210_sd_config)中才会生成这个文件。因此这个文件的值和我们配置过程有关,是由配置过程根据我们的配置自动生成的。
    (2)我们X210在iNand情况下配置生成的config.mk内容为:
    ARCH = arm
    CPU = s5pc11x
    BOARD = x210
    VENDOR = samsung
    SOC = s5pc110

    (3) export导出了这5个变量作为环境变量。所以着两行加起来其实就是为当前makefile定义了5个环境变量而已。之所以不直接给出这5个环境变量的值,是因为我们希望这5个值是可以被人很容易的、集中的配置的。

    x210_sd_config :	unconfig
    	@$(MKCONFIG) $(@:_config=) arm s5pc11x x210 samsung s5pc110
    	@echo "TEXT_BASE = 0xc3e00000" > $(obj)board/samsung/x210/config.mk

    (4)这里的配置值来自于以上代码的配置项。如果我们要更改这里的某个配置值要到此处调用MKCONFIG脚本传参时的参数。

    4、ARCH CROSS_COMPILE
    (1)上面导出的,值来自于我们的配置过程,它的值会影响后面的CROSS_COMPILE环境变量的值。ARCH的意义是定义当前编译的目标CPU的架构。
    (2)CROSS_COMPILE是定义交叉编译工具链的前缀的。定义这些前缀是为了在后面用(用前缀加上后缀来定义编译过程中用到的各种工具链中的工具)。我们把前缀和后缀分开还有一个原因就是:在不同CPU架构上的交叉编译工具链,只是前缀不一样,后缀都是一样的。因此定义时把前缀和后缀分开,只需要在定义前缀时区分各种架构即可实现可移植性。

    ifndef CROSS_COMPILE
    ifeq ($(HOSTARCH),$(ARCH))
    CROSS_COMPILE =
    else
    ifeq ($(ARCH),ppc)
    CROSS_COMPILE = ppc_8xx-
    endif
    ifeq ($(ARCH),arm)
    #CROSS_COMPILE = arm-linux-
    #CROSS_COMPILE = /usr/local/arm/4.4.1-eabi-cortex-a8/usr/bin/arm-linux-
    #CROSS_COMPILE = /usr/local/arm/4.2.2-eabi/usr/bin/arm-linux-
    CROSS_COMPILE = /usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-
    endif
    ifeq ($(ARCH),i386)
    CROSS_COMPILE = i386-linux-
    endif
    ifeq ($(ARCH),mips)
    CROSS_COMPILE = mips_4KC-
    endif
    ifeq ($(ARCH),nios)
    CROSS_COMPILE = nios-elf-
    endif
    ifeq ($(ARCH),nios2)
    CROSS_COMPILE = nios2-elf-
    endif
    ifeq ($(ARCH),m68k)
    CROSS_COMPILE = m68k-elf-
    endif
    ifeq ($(ARCH),microblaze)
    CROSS_COMPILE = mb-
    endif
    ifeq ($(ARCH),blackfin)
    CROSS_COMPILE = bfin-uclinux-
    endif
    ifeq ($(ARCH),avr32)
    CROSS_COMPILE = avr32-linux-
    endif
    ifeq ($(ARCH),sh)
    CROSS_COMPILE = sh4-linux-
    endif
    ifeq ($(ARCH),sparc)
    CROSS_COMPILE = sparc-elf-
    endif	# sparc
    endif	# HOSTARCH,ARCH
    endif	# CROSS_COMPILE
    
    export	CROSS_COMPILE

    (3)CROSS_COMPILE在源码的136-182行来确定。CROSS_COMPILE是被ARCH所确定的,只要配置了ARCH=arm,那么我们就只能在ARM的那个分支去设置CROSS_COMPILE的值。这个设置值只要能保证找到那个交叉编译工具链即可,不一定非得是全路径的,相对路径也可以。(如果已经将工具链导出到环境变量,并且设置了符号链接,这样CROSS_COMPILE = arm-linux-就可以)
    (4)实际运用时,我们可以在Makefile中去更改设置CROSS_COMPILE的值,也可以在编译时用make CROSS_COMPILE=xxxx来设置,而且编译时传参的方法可以覆盖Makefile里面的设置。

    # load other configuration
    include $(TOPDIR)/config.mk
    

      

    (1)autoconfig.mk文件不是源码提供的,是配置过程自动生成的。
    (2)这个文件的作用就是用来指导整个uboot的编译过程。这个文件的内容其实就是很多CONFIG_开头的宏(可以理解为变量),这些宏/变量会影响我们uboot编译过程的走向(原理就是条件编译)。在uboot代码中有很多地方使用条件编译进行编写,这个条件编译是用来实现可移植性的。(可以说uboot的源代码在很大程度来说是拼凑起来的,同一个代码包含了各种不同开发板的适用代码,用条件编译进行区别。)
    (3)这个文件不是凭空产生的,配置过程也是需要原材料来产生这个文件的。原材料在源码目录的inlcude/configs/xxx.h头文件。(X210开发板中为include/configs/x210_sd.h)。这个h头文件里面全都是宏定义,这些宏定义就是我们对当前开发板的移植。每一个开发板的移植都对应这个目录下的一个头文件,这个头文件里每一个宏定义都很重要,这些配置的宏定义就是我们移植uboot的关键所在。

    2.4.5.uboot主Makefile分析5
    2.4.5.1、链接脚本(config.mk 142-149行)
    (1)如果定义了CONFIG_NAND_U_BOOT宏,则链接脚本叫u-boot-nand.lds,如果未定义这个宏则链接脚本叫u-boot.lds。
    (2)从字面意思分析,即可知:CONFIG_NAND_U_BOOT是在Nand版本情况下才使用的,我们使用的X210都是iNand版本的,因此这个宏没有的。
    (3)实际在boardsamsungx210目录下有u-boot.lds,这个就是链接脚本。我们在分析uboot的编译链接过程时就要考虑这个链接脚本。

    2.4.5.2、TEXT_BASE(config.mk 156-158行)
    (1)Makefile中在配置X210开发板时,在board/samsung/x210目录下生成了一个文件config.mk,其中的内容就是:TEXT_BASE = 0xc3e00000相当于定义了一个变量。
    (2)TEXT_BASE是将来我们整个uboot链接时指定的链接地址。因为uboot中启用了虚拟地址映射,因此这个C3E00000地址就等于0x23E00000(也可能是33E00000具体地址要取决于uboot中做的虚拟地址映射关系)。
    (3)回顾裸机中讲的链接地址的问题,再想想dnw方式先下载x210_usb.bin然后再下载uboot.bin时为什么第二个地址是23E00000.

    2.4.5.3、自动推导规则(config.mk 239-256行)
    (1)我们在讲Makefile时提到过自动推导规则,具体理解可以参考《跟我一起学Makefile》

    2.4.6.uboot主Makefile分析6
    (1)291行出现了整个主Makefile中第一个目标all(也就是默认目标,我们直接在uboot根目录下make其实就等于make all,就等于make这个目标)
    (2)目标中有一些比较重要的。譬如:u-boot是最终编译链接生成的elf格式的可执行文件,
    (3)unconfig字面意思来理解就是未配置。这个符号用来做为我们各个开发板配置目标的依赖。目标是当我们已经配置过一个开发板后再次去配置时还可以配置。
    (4)我们配置开发板时使用:make x210_sd_config,因此分析x210_sd_config肯定是主Makefile中的一个目标。

  • 相关阅读:
    xml方式将dataset导出excel
    linux安装Navicat,界面出现乱码解决方法 (转发)
    ERROR 29 (HY000): File '/var/lib/mysql/txtdata/yz2014_1.txt' not found (Errcode: 13 "Permission denied")
    centos7中yum安装ntfs3g(转载)
    MariaDB中my.cnf文件误删除
    Mysql操作命令出现错误时消除/mysql数据导入txt
    Linux查找yum安装软件在系统中路径
    Centos7安装MariaDB安装数据库yum安装数据库远程登录数据库存储路径更改
    Zookeeper常用命令
    Hbase学习连接-数据导入
  • 原文地址:https://www.cnblogs.com/yygsj/p/5313489.html
Copyright © 2011-2022 走看看