• 二、主目录 Makefile 分析(1)


    2.1 uboot 版本号

      uboot 的版本号分三个级别:

    • VERSION:主版本号
    • PATCHLEVEL:次版本号,为补丁级别
    • SUBLEVEL:再次版本号
    • EXTRAVERSION:附加版本信息。这个一般使给自己用的,可以定义为字符串如”JH“
    • U_BOOT_VERSION:版本号
    • VERSION_FILE:版本文件变量

      这4个用.分隔开共同构成了最终的版本号。  

      Makefile 中的版本号最终生成了一个变量 UBOOTVERSION,这个变量记录了 Makefile 中配置的版本号。

      include/version_autogenerated.h文件是编译过程中自动生成的一个文件,所以源目录中没有,但是编译过后的uboot中就有了。它里面的内容是一个宏定义,宏定义的值内容就是我们在Makefile中配置的uboot的版本号。

      24-29行:

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

      obj 变量定义在后面, makefile 中若是有等号,则变量取用最后定义的,若是源码目录编译,没指定O的值的话,obj为空,则放在 include 文件夹下

    2.2 HOSTARCH 和 HOSTOS 

      HOSTARCH:主机CPU架构;HOST是主机,就是当前做开发用的CPU或电脑;ARCH是架构,表示CPU的架构。

      HOSTOS:主机的操作系统

      这两个变量是用 export 导出的环境变量,

      uname 是shell 脚本命令 uname -m 命令是得到CPU的类型

      uname -s 显示操作系统类型

      sed -e:以选项中的指定的 cript 来处理输入的文本文件

      tr命令可以对来自标准输入的字符进行替换、压缩和删除。

      tr '[:upper:]' '[:lower:]':将大写字符转换为小写字符

      31-42行

     1 HOSTARCH := $(shell uname -m | 
     2     sed -e s/i.86/i386/ 
     3         -e s/sun4u/sparc64/ 
     4         -e s/arm.*/arm/ 
     5         -e s/sa110/arm/ 
     6         -e s/powerpc/ppc/ 
     7         -e s/macppc/ppc/)
     8 
     9 HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | 
    10         sed -e 's/(cygwin).*/cygwin/')
    11 
    12 export    HOSTARCH HOSTOS

    2.3 VENDOR

    1 VENDOR=  #表示开发商

    2.4 编译方法

      U-boot 的编译过程可以支持向一个自己定义的路径生成最终的目标文件。这里提供两种方法:

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

      命令行'O='设置会覆盖环境变量BUILD_DIR的设置 

      如果都不采用上面两种方法,那么目标文件放到源码顶层目录,也就是U-BOOT顶层目录  

      代码 69 到 98行

     1 ifdef O
     2 ifeq ("$(origin O)", "command line")
     3 BUILD_DIR := $(O)
     4 endif
     5 endif
     6 
     7 ifneq ($(BUILD_DIR),)
     8 saved-output := $(BUILD_DIR)
     9 
    10 # Attempt to create a output directory.
    11 $(shell [ -d ${BUILD_DIR} ] || mkdir -p ${BUILD_DIR})
    12 
    13 # Verify if it was successful.
    14 BUILD_DIR := $(shell cd $(BUILD_DIR) && /bin/pwd)
    15 $(if $(BUILD_DIR),,$(error output directory "$(saved-output)" does not exist))
    16 endif # ifneq ($(BUILD_DIR),)
    17 
    18 OBJTREE        := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))
    19 SRCTREE        := $(CURDIR)
    20 TOPDIR        := $(SRCTREE)
    21 LNDIR        := $(OBJTREE)
    22 export    TOPDIR SRCTREE OBJTREE
    23 
    24 MKCONFIG    := $(SRCTREE)/mkconfig
    25 export MKCONFIG
    26 
    27 ifneq ($(OBJTREE),$(SRCTREE))
    28 REMOTE_BUILD     := 1
    29 export REMOTE_BUILD
    30 endif

      100到110行,实现 编译目录和源代码目录不相同的时候执行 obj赋值,如果是在源码目录赋值,则 obj 和 src  都为空

    • OBJTREE:编译出的.o文件存放的目录的根目录。在默认编译下,OBJTREE等于当前目录;在O=xx编译下,OBJTREE就等于我们设置的那个输出目录。
    • SRCTREE: 源码目录,其实就是源代码的根目录,也就是当前目录。 
    • TOPDIR:若是 make -O 则此值为 SRCTREE,也就是源码根目录
    • LNDIR:链接目录,也是需要 O=XX 编译,此情况下为我们输出的目录,也就是 OBJTREE
     1 # $(obj) and (src) are defined in config.mk but here in main Makefile
     2 # we also need them before config.mk is included which is the case for
     3 # some targets like unconfig, clean, clobber, distclean, etc.
     4 ifneq ($(OBJTREE),$(SRCTREE))
     5 obj := $(OBJTREE)/
     6 src := $(SRCTREE)/
     7 else
     8 obj :=
     9 src :=
    10 endif
    11 export obj src

      执行完毕后,将 obj src 值输出成环境变量,供 u-boot  其他文件中调用 

      总结:在默认编译下,OBJTREE和SRCTREE相等;在O=xx这种编译下OBJTREE和SRCTREE不相等。Makefile中定义这两个变量,其实就是为了记录编译后的.o文件往哪里放,就是为了实现O=xx的这种编译方式的。

    2.5 MKCONFIG

      代码在 92 93 行:

    1 MKCONFIG    := $(SRCTREE)/mkconfig
    2 export MKCONFIG

      Makefile中定义的一个变量(在这里定义,在后面使用),它的值就是我们源码根目录下面的mkconfig。这个mkconfig是一个脚本,这个脚本就是uboot配置阶段的配置脚本。

    2.6 编译选项---CROSS_COMPILE

    • CROSS_COMPILE 是定义交叉编译工具链的前缀的。
    • 定义这些前缀是为了在后面用(用前缀加上后缀来定义编译过程中用到的各种工具链中的工具)。
    • 我们把前缀和后缀分开还有一个原因就是:在不同CPU架构上的交叉编译工具链,只是前缀不一样,后缀都是一样的。
    • 因此定义时把前缀和后缀分开,只需要在定义前缀时区分各种架构即可实现可移植性。

      代码在 112 到 161 行:

     1 #########################################################################
     2 # 此句判断有没有生成include/config.mk文件,有这个文件则makefile 认为是配置过了 make xxx_defconfig。
     3 ifeq ($(OBJTREE)/include/config.mk,$(wildcard $(OBJTREE)/include/config.mk))
     4 
     5 # load ARCH, BOARD, and CPU configuration,包含 include/config.mk 文件
     6 include $(OBJTREE)/include/config.mk
     7 export    ARCH CPU BOARD VENDOR SOC  
     8 
     9 ifndef CROSS_COMPILE
    10 ifeq ($(HOSTARCH),ppc)
    11 CROSS_COMPILE =
    12 else
    13 ifeq ($(ARCH),ppc)
    14 CROSS_COMPILE = powerpc-linux-
    15 endif
    16 ifeq ($(ARCH),arm)
    17 CROSS_COMPILE = arm-linux-
    18 endif
    19 ifeq ($(ARCH),i386)
    20 ifeq ($(HOSTARCH),i386)
    21 CROSS_COMPILE =
    22 else
    23 CROSS_COMPILE = i386-linux-
    24 endif
    25 endif
    26 ifeq ($(ARCH),mips)
    27 CROSS_COMPILE = mips_4KC-
    28 endif
    29 ifeq ($(ARCH),nios)
    30 CROSS_COMPILE = nios-elf-
    31 endif
    32 ifeq ($(ARCH),nios2)
    33 CROSS_COMPILE = nios2-elf-
    34 endif
    35 ifeq ($(ARCH),m68k)
    36 CROSS_COMPILE = m68k-elf-
    37 endif
    38 ifeq ($(ARCH),microblaze)
    39 CROSS_COMPILE = mb-
    40 endif
    41 ifeq ($(ARCH),blackfin)
    42 CROSS_COMPILE = bfin-elf-
    43 endif
    44 ifeq ($(ARCH),avr32)
    45 CROSS_COMPILE = avr32-
    46 endif
    47 endif
    48 endif
    49 
    50 export    CROSS_COMPILE
    • wildcard:在规则中,通配符会被自动展开。 但在变量的定义和函数引用时,通配符将失效。这种情况下如果需要通配符有效,就需要使用函数“ wildcard”,它的用法是: $(wildcard PATTERN...) 。
      • 在 Makefile 中,它被展开为已经存在的、使用空格分开的、匹配此模式的所有文件列表。如果不存在任何符合此模式的文件,函数会忽略模式字符并返回空。 
    • 此段代码是先判断 include/config.mk 是否存在,若存在,则在主 Makefile 中包含此文件,导出 config.mk 中的变量ARCH CPU BOARD VENDOR SOC
      • include/config.mk 不是源码自带的(没有编译过的源码目录下是找不到这个文件的),要在配置过程(make xx_defconfig)中才会生成这个文件。因此这个文件的值和我们配置过程有关,是由配置过程根据我们的配置自动生成的。  
    • 接下来,判断编译,即 make 的时候是否传入参数 CROSS_COMPILE,如果没有定义,则在主Makefile 中定义CROSS_COMPILE 环境变量,最后导出 CROSS_COMPILE
      • ARCH 变量:这是 include/config.mk 中导出的,也就是在我们的配置过程中生成的,ARCH的意义是定义当前编译的目标CPU的架构  

       

  • 相关阅读:
    网店系统H5版(一)
    php date()方法传入时间戳为空时返回1970-01-01
    MySQL实用语句
    HTTPS和SSL握手过程(转载)
    jinfo
    linux下以‘-’开头的文件名
    ssh连接服务器失败解决记录
    Linux时区详解
    fiddler抓包url有乱码
    mysql灾备演练问题
  • 原文地址:https://www.cnblogs.com/kele-dad/p/8886934.html
Copyright © 2020-2023  润新知