zoukankan      html  css  js  c++  java
  • 二、主目录 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的架构  

       

  • 相关阅读:
    how to pass a Javabean to server In Model2 architecture.
    What is the Web Appliation Archive, abbreviation is "WAR"
    Understaning Javascript OO
    Genetic Fraud
    poj 3211 Washing Clothes
    poj 2385 Apple Catching
    Magic Star
    关于memset的用法几点
    c++ 函数
    zoj 2972 Hurdles of 110m
  • 原文地址:https://www.cnblogs.com/kele-dad/p/8886934.html
Copyright © 2011-2022 走看看