一、预习Makefile
二、Android编译系统的层次
三、Android编译系统的常用配置文件
四、 Android编译系统的流程
五、Android编译系统的使用


 


一、预习Makefile



  Makefile的规则:
    target ... : prerequisites ...
      command
            ...
            ...
  target也就是一个目标文件,可以是Object File,也可以是执行文件。还可以是一个标签(Label)。
  prerequisites就是,要生成那个target所需要的文件或是目 标。
  command也就是make需要执行的命令。(任意的Shell命令)
  这是一个文件的依赖关系,也就是说,target这 一个或多个的目标文件依赖于prerequisites中的文件,
  其生成规则定义在command中。 说白一点就是说,prerequisites中如果有一个以上的文件比target文


  件要新的话,command所定义的命令就会被执行。这就是 Makefile的规则。也就是Makefile中最核心的


  内容。正如上面作者所述,上面是Makefile中最核心的内容,Android编译系统符合GNU make的标准,
  当然这 也是Android 编译系统最核心的内容。
  
二、Android编译系统的层次



  Android编译系统(build system)集中于Android源码下的build/core下,在Android2.2中,共有


  56个*.mk文件。另外还有一些shell脚本。Android编译系统完成的并不仅仅是对目标(主机)系统二进


  制文件、java应用程序的编译、链接、打包等,而且还有包括生成各种依赖关系、确保某个模块的修改引起


  相依赖的文件的重新编译链接,甚至还包括目标文件系统的生成,配置文件的生成等,因此Android编译系


  统具有支持多架构(linux-x86、windows、arm等)、多语言(汇编、C、C++、Java等)、多目标、多


  编译方式。
  
  编译层次包含了下表描述的抽象层。每一层都与一个或多个层相关联。例如,一个arch有多个 board,每个


  board有多个device。你可以在一个层中定义一个元素,以达到排除复制,简化维护的目的。



  Layer                  Example                      Description


  Product    myProduct, myProduct_eu, j2, sdk  产品层定义完整的移植产品的语法。


             myProduct_eu_fr,                  定义要编译哪些模块,怎么配置。基于区域


                                               或者基于特性,比如照相机,你可能要提供几


                                               个不同的版本。


  Device    myDevice, myDevice_eu,             设备层代表设备的物理层。例如,北美设备可


            myDevice_eu_lite                   能包含QWERTY键盘,而在法国售卖的设备可能


                                               包含AZERTY键盘。外围设备一般与设备层连接


                        


  Board     sardine, trout, goldfish           电路板层代表产品的原始图。可能还有外围设备


                                               连接到这一层。


  Arch     arm (arm5te) (arm6), x86, 68k       体系层描述了在电路版上运行的处理器。


 


三、Android编译系统的常用配置文件


 


  在Android中,主要的Makefile文件存在于build/core/目录下,它的表现形式为多个后缀为mk的文件组


  成,也称为build system。Android build system 主要有两大部分构成:配置部分,目标构建部分。


  Build system的主流程文件为build/core/main.mk文件。
  几个很重要的*.mk文件如下:
  
    buildspec.mk: 位于根目录下,可在此选择要产生的product 、平台、额外的module/package等。


        build/buildspec.mk.default是样板。  
    AndroidProducts.mk: 即为Android build system提供给厂商的接口文件。通过此文件即可定义所


        需编译和安装的packages(也即应用程序)。缺省选项是generic。  
    BoardConfig.mk: 是为product主板做设定,例如driver选择设定,选择CPU架构等等。
    Android.mk:是 module 和 package 的设置文件,每个 module/package 的目录下都会有一个


        Android.mk。所谓的 module 是指系统的 native code ,相对于用 Java写成的


        Androidapplication 称为 package。
    Build/envsetup.mk:编译环 境初始化,定义一些实用的shell函数,方便编译使用。
    build/core/Makefile:包含build/core /main.mk,此文件主要控制生成 


        system.img,ramdisk.img,userdata.img,以及recorvery image,sdk等。
    main.mk: 实际的主控Makefile,例如找到TOP目录下所有Android.mk文件。
    config.mk:定义了编译目标程序所需的工具链 及编译参数。
    base_rules.mk:对一些Makefile的变量规则化
    Binary.mk:控制如何生成目标文 件
    Clear_vars.mk:清除编译系统中用到的临时变量
    definations.mk:定义了很多编译系统中用到 的宏,相当于函数库
    Copy_headers.mk:将头文件拷贝到指定目录
    Combo/linux-arm.mk:控 制如何生成linux-arm二进制文件,包括ARM相关的编译器,编译参数等的


        设置
    build/envsetup.sh:提供了几个有用的命令,执行 . build/envsetup.sh(.后面有空格)。
    
  注:其中对模块编译有帮助的是tapas、m、mm、mmm这几个命 令。
  
      1、tapas——以交互方式设置build环境变量。
        输入:tapas
           第 一步,选择目标设备:
             例如 我们选择1
           第二步,选择代码格式:
             我 们选择1
           第三步,选择产品平台:
             注意:这里,Google源代码里默认是 generic。
             
      2、m、mm、mmm使用独立模块的make命令
        m 从根目录开始编译;
        mm 编译当前目录下的所有模块;
        mmm 编译指定目录下的所有模块;
  
四、 Android编译系统的流程


 


  主要流程都是由 build/core/main.mk 所安排的。
    1、初始化相关变量
    2、检测编译环 境和目标环境
    3、决定目标product
    4、读取 product 的设定
    5、读取 product 所指定之目标平台架构设定
    6、选择 toolchain
    7、指定编译参数 (*-.mk)
    8、 清除输出目录
    9、设定/检查版本编号
    10、读取所有 BoardConfig.mk 文件
    11、 读取所有 module 的设定
    12、根据设定,产生必需的 rule
    13、产生 image
  
  1、 初始化和检测
  
    由 build/core/config.mk 进行。 build/core/envsetup.mk 检查 developer 的设定 


    (buildspec.mk),并检查执行环境,以决定输出目录和环境。build/core/config.mk 本身还依据


    参数,决定解释时的相关参数,例如 compiler 的路径、flags, lex 、yacc 的路径参数等。关于


    product的相关设定,则是由build/core/product_config.mk 所处理,使用


    build/core/product.mk提供之 macro 载入。根据 AndroidProduct.mk 的內容,


    product_config.mk 决定了:PRODUCT_TAGS,OTA_PUBLIC_KEYS,PRODUCT_POLICY等。
    
  2、Product 设定的读取



    Android product 的设定来自于build/target/product/AndroidProduct.mk 和 vendor 子目


    录下AndroidProduct.mk 。building system透过 find 指令,找出所有可能的


    AndroidProduct.mk。AndroidProduct.mk里定义PRODUCT_MAKEFILES变量,列举所有实际定义


    product的 makefile。这些makefile 各自定义独立的 product。product 相关参数,存成


    PRODUCTS. . 形式的变量。并将makefile 路径存在 PRODUCTS 变量。因此,透过 PRODUCTS 能取


    得所有的 product 路径/名称,并透过 PRODUCTS. . 形式的变量取得內容。
  
  3、 Module 设定的读取



    Module 是指 native code 的软件模块,而 Java application 則被称为 package。


    build/core/definitions.mk 定义module/package 相关 macro ,读取、检查


    module/package 定义档;分散 source tree 各处的 Android.mk 文件。 
    build/core/main.mk 使用 find 指令,在这些子目录下找出所有 Android.mk ,并将路径存在


    subdir_makefiles 变量里。最后,include 这些文件。这些Android.mk 会 include 定义成变量


    BUILD_SHARED_LIBRARY 、BUILD_PACKAGE 等,和其目的相配的 makefile。这些 makefile 会


    变 Android.mk 定义之內容,存成 ALL_MODULES. Android.mk>. 的形式。例如,Android.mk 定


    义了LOCAL_MODULE_SUFFIX ,会变存成 ALL_MODULES.


    Android.mk>.LOCAL_MODULE_SUFFIX 。而 Android.mk 路径, 同样会存于ALL_MODULES 变量


    里。查找 Android.mk 的路径,基本上会是整个 source tree 。但会依特定的 goal , 选择性只


    找寻特定目录。例如 SDK 只需特定目录下的 Android.mk 。


 


  4、Board Level 设定



    和目标平台主板相关之设定,例如使用了什么装置、driver 等,或是是否需要编译bootloader 、


    kernel等,都是在 BoardConfig.mk 里设定。同样,每张主板可以有不同设定,存在不同目录下的


    BoardConfig.mk,以 find 寻找如下文件:
      build/target/board/$(TARGET_DEVICE)/BoardConfig.mk
      device$(TARGET_DEVICE)/BoardConfig.mk
    TARGET_DEVICE 是 product 所定义,因此同一个 BoardConfig.mk 可被多个 product 所使用。
    一个 TARGET_DEVICE ,通常只有一个 BoardConfig.mk 。 BoardConfig.mk 会被直接


    include 到 building system 的 name space 里。 因此,一些 module 的


    enable/disable ,可以在 BoardConfig.mk 以对应不同的主板。


 


  5、Rules



    在 module 的定义文件 Android.mk 裡,可定义 module 的 tag, LOCAL_MODULE_TAGS, 以分


    类这些 module。每一个 product 可以指定需要的 tag (PRODUCT_TAGS),使 building system


    只便宜标示这些 tag 的 module。在 build/core/main.mk 里,所有标示特定 tag 的 module 收


    集为 ALL_DEFAULT_INSTALLED_MODULES,并 include build/core/Makefile 处理。
    build/core/Makefile 为这些 module 产生 rule ,并使产生 image 的 goal depend on 这


    些 rule ,使这些 module 被编译。


 


五、Android编译系统的使用
  
  下面两种方法,第一个产生更稳定的结果。


 


  方法一:


    创建buildspec.mk的本地版本。最容易的方法是进入你的设备目录,


    执行下列指令:


  

cp buildspec.mk.default buildspec.mk ; chmod u=rw buildspec.mk

 


    默认的buildspec.mk文件,所有的选项都是被注释的,为了建立个性化的配置环境,可以编辑


    buildspec.mk.
    一般设置如下选项就可以拉:
      BUILD_ENV_SEQUENCE_NUMBER := 9
      TARGET_BOARD_PLATFORM := imx53
      TARGET_PRODUCT := mine_mx53


    一旦建立了配置文件,然后复制到根目录下,就能够通过执行make编译设备代码,在第一次执行这个命令


    的时候,会花费很长时间,在双核机器上,考虑使用’-j2’(甚至’j4’)以加速编译。


    make -j2


 


  方法二:


    做一个通用的版本,
    执行
      source //device/envsetup.sh, 这个文件包含了必要的变量和函数定义,下面有描述:


cd $TOP 
 
       .envsetup.sh 
 
       partner_setup generic  //select generic as the product 
 
       make -j4 PRODUCT-generic-user 
 
        
 
       //你也可以用eng替换user, 生成一个调式版。 
 
       make -j4 PRODUCT-generic-eng