• Tiny4412 Android 5.0 编译系统学习笔记


    1.Android 编译系统概述

    Build 系统中最主要的处理逻辑都在 Make 文件中,而其他的脚本文件只是起到一些辅助作用。
    整个 Build 系统中的 Make 文件可以分为三类:
    ① Build 系统核心文件,此类文件定义了整个 Build 系统的框架,而其他所有 Make 文件都是在这个框架的基础上编写出来的。Build 系统核心文件全部位于 /build/core目录下。

     ②针对某个产品(一个产品可能是某个型号的手机或者平板电脑)的 Make 文件,这些文件通常位于 device 目录下,该目录下又以公司名以及产品名分为两级目录对于一个产品的定义通常需要一组文件,这些文件共同构成了对于这个产品的定义。

     ③第三类是针对某个模块的 Make 文件。整个系统中,包含了大量的模块,每个模块都有一个专门的 Make 文件,这类文件的名称统一为“Android.mk”,该文件中定义了如何编

    译当前模块。Build 系统会在整个源码树中扫描名称为“Android.mk”的文件并根据其中的内容执行模块的编译

    2.编译Tiny4412 Android系统

    编译Android系统命令如下:

    source build/envsetup.sh
    lunch full_tiny4412-eng
    make -j4
    ①第一行命令“source build/envsetup.sh”引入了 build/envsetup.sh脚本。该脚本的作用是初始化编译环境,并引入一些辅助的 Shell 函数,这其中就包括第二步使用 lunch 函
    数。它还会引入device/company/product/vendorsetup.sh
    ②第二行命令“lunch full-eng”是调用 lunch 函数,并指定参数为full_tiny4412-eng。lunch 函数的参数用来指定此次编译的目标设备以及编译类型。调用lunch函数
    首先执行add_lunch_combo()函数 这样就显示一个列表,当你选择后 系统会调用choosecombo()后 会预先设置值一些环境变量 并且调用config.mk ,
    所有跟config.mk有关的后面的步骤都是这个时候执行的。命令行也可以看到一系列的环境变量显示,实现该命令是 dumpvar.mk。
    调用make 执行make droidcore ,主要提取了Android.mk的定义规则 并找到整个系统有关该文件的脚本 做一个系统级的编译。

    3.源码编译过程分析

    整个 Build 系统的入口文件是源码树根目录下的“Makefile”的文件,当在源代码根目录上调用 make 命令时,make 命令首先将读取该文件。它的内容如下。

    ### DO NOT EDIT THIS FILE ###
    include build/core/main.mk
    ### DO NOT EDIT THIS FILE ###

    它引用了 build/core/main.mk 文件。 main.mk 文件中又引用了其他.mk文件,其他.mk文件中又会包含更多的.mk文件,这样就将了整个 Build 系统串联起来了。

    3.1 主要的 Make 文件的说明

    文件名说明
    main.mk 最主要的 Make 文件,该文件中首先将对编译环境进行检查,同时引入其他的 Make 文件,设置全局变量
    和几个最主要的Make目标,比如Droid、sdk等
    help.mk 包含了名称为 help 的 Make 目标的定义,该目标将列出主要的 Make 目标及其说明。
    pathmap.mk 将许多头文件的路径通过名值对的方式定义为映射表,并提供 include-path-for 函数来获取。例如,通过$(call include-path-for, frameworks-native)便可以获取到 framework 本地代码需要的头文件路径。
    envsetup.mk 配置 Build 系统需要的环境变量,例如:TARGET_PRODUCT,TARGET_BUILD_VARIANT,HOST_OS,HOST_ARCH 等。当前编译的主机平台信息(例如操作系统,CPU 类型等信息)就是在这个文件中确定的。另外,该文件中还指定了各种编译结果的输出路径。
    combo/select.mk 根据当前编译器的平台选择平台相关的 Make 文件。
    dumpvar.mk 在 Build 开始之前,显示此次 Build 的配置信息。
    config.mk 整个 Build 系统的配置文件,最重要的 Make 文件之一。该文件中主要包含以下内容:
    • 定义了许多的常量来负责不同类型模块的编译。
    • 定义编译器参数以及常见文件后缀,例如 .zip,.jar.apk。
    • 根据 BoardConfig.mk 文件,配置产品相关的参数。
    • 设置一些常用工具的路径,例如 flex,e2fsck,dx。
    definitions.mk 最重要的 Make 文件之一,在其中定义了大量的函数。这些函数都是 Build 系统的其他文件将用到的。例如:my-dir,all-subdir-makefiles,find-subdir-files,sign-package 等,关于这些函数的说明请参见每个函数的代码注释。
    distdir.mk 针对 dist 目标的定义。dist 目标用来拷贝文件到指定路径。
    dex_preopt.mk 针对启动 jar 包的预先优化。
    pdk_config.mk 顾名思义,针对 pdk(Platform Developement Kit)的配置文件。
    ${ONE_SHOT_MAKEFILE} ONE_SHOT_MAKEFILE 是一个变量,当使用“mm”编译某个目录下的模块时,此变量的值即为当前指定路径下的 Make 文件的路径。
    ${subdir_makefiles} 各个模块的 Android.mk 文件的集合,这个集合是通过 Python 脚本扫描得到的。
    post_clean.mk 在前一次 Build 的基础上检查当前 Build 的配置,并执行必要清理工作。
    legacy_prebuilts.mk 该文件中只定义了 GRANDFATHERED_ALL_PREBUILT 变量。
    Makefile 被 main.mk 包含,该文件中的内容是辅助 main.mk 的一些额外内容。

     3.2 主要Makefile的调用流程

    build/core/main.mk主要流程为:

    l  初始化相关的参数设置(buildspec.mk、envsetup.mk、config.mk)

    l  检测编译环境和目标环境

    l  决定目标product

    l  读取product的配置信息及目标平台信息

    l  清除输出目录

    l  检查版本号

    l  读取Board的配置

    l  读取所有Module的配置

    l  根据配置产生必要的规则(build/core/Makefile)

    l  生成image

    ①main.mk:它是整个系统编译系统主导文件,它的主要内容如下
    #定义默认的target即make命令后不加参数的默认目标
    # This is the default target.  It must be the first declared target.
    .PHONY: droid
    DEFAULT_GOAL := droid
    $(DEFAULT_GOAL):
    #引入help.mk,help.mk    包含了名称为 help 的 Make 目标的定义,
    #该目标将列出主要的 Make 目标及其说明
    # Targets that provide quick help on the build system.
    include $(BUILD_SYSTEM)/help.mk
    #引入config.mk,定义产品,主机的各种基本变量
    # Set up various standard variables based on configuration
    # and host information.
    include $(BUILD_SYSTEM)/config.mk
    #引入clean操作的定义
    # This allows us to force a clean build - included after the config.mk
    # environment setup is done, but before we generate any dependencies.  This
    # file does the rm -rf inline so the deps which are all done below will
    # be generated correctly
    include $(BUILD_SYSTEM)/cleanbuild.mk
    #引入基本编译系统的定义,提供了大量的实用函数
    # Bring in standard build system definitions.
    include $(BUILD_SYSTEM)/definitions.mk
    #读取android源码树中所有的Android.mk
    ifneq ($(dont_bother),true)
    #
    # Include all of the makefiles in the system
    #
    # Can't use first-makefiles-under here because
    # --mindepth=2 makes the prunes not work.
    subdir_makefiles := 
        $(shell build/tools/findleaves.py --prune=$(OUT_DIR) --prune=.repo --prune=.git $(subdirs) Android.mk)
    $(foreach mk, $(subdir_makefiles), $(info including $(mk) ...)$(eval include $(mk)))

    ②config.mk解析:产品配置主导文件

    #引入envsetup.mk定义大部分全局变量,配置编译时的环境变量。
    #该文件可以指定用户编译配置
    # ---------------------------------------------------------------
    # Define most of the global variables.  These are the ones that
    # are specific to the user's build configuration.
    include $(BUILD_SYSTEM)/envsetup.mk

    ③envsetup.mk:用来配置编译时的环境变量

    #引入BoardConfig.mk,BoardConfig.mk主要写了product使用的硬件所支持和不支持的功能性内容。
    #BroadConfig.mk设置了每个设备的自己的一些变量值,来区别编译时的行为
    include $(board_config_mk)
    ......
    # Boards may be defined under $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)
    # or under vendor/*/$(TARGET_DEVICE).  Search in both places, but
    # make sure only one exists.
    # Real boards should always be associated with an OEM vendor.
    board_config_mk := 
        $(strip $(wildcard 
            $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)/BoardConfig.mk 
            $(shell test -d device && find device -maxdepth 4 -path '*/$(TARGET_DEVICE)/BoardConfig.mk') 
            $(shell test -d vendor && find vendor -maxdepth 4 -path '*/$(TARGET_DEVICE)/BoardConfig.mk') 
        ))
    #设置版本信息
    # Set up version information.
    include $(BUILD_SYSTEM)/version_defaults.mk
    #引入产品级别的配置
    # Read the product specs so we can get TARGET_DEVICE and other
    # variables that we need in order to locate the output files.
    include $(BUILD_SYSTEM)/product_config.mk

    ④product_config.mk:产品级别的配置,读取指定的目录下所有的AndrodProducts.mk文件中定义的产品信息

    #引用AndroidProducts.mk
    #读取AndrodProducts.mk文件中定义的产品信息
    ifneq ($(strip $(TARGET_BUILD_APPS)),)
    # An unbundled app build needs only the core product makefiles.
    all_product_configs := $(call get-product-makefiles,
        $(SRC_TARGET_DIR)/product/AndroidProducts.mk)
    else
    # Read in all of the product definitions specified by the AndroidProducts.mk
    # files in the tree.
    all_product_configs := $(get-all-product-makefiles)
    endif
    ⑤AndroidProducts.mk
    列出了产品版本定义文件名的列表 该列表下的文件定义了产品的各种版本信息
    ⑥BoardConfig.mk
    该文件用来配置产品,它其中定义的都是设备底层的硬件特性,例如该设备的板级相关信息,Wifi相关信息以及bootloader和内核等信息。
     
     
     
    参考文章:
    http://www.ibm.com/developerworks/cn/opensource/os-cn-android-build/
    http://www.jianshu.com/p/6d0e3492c91e
     
  • 相关阅读:
    内存泄露检测工具之DMalloc
    五年后你在何方
    程序员技术练级攻略
    Windows编程革命简史
    su的时候密码认证失败的解决方法
    ruby 元编程 meta programming
    内存对齐分配策略(含位域模式)
    Ruby 之 Block, Proc, Lambda 联系区别,转载
    c++异常处理机制示例及讲解
    ruby 常见问题集 1 不断更新中
  • 原文地址:https://www.cnblogs.com/CoderTian/p/5927405.html
Copyright © 2020-2023  润新知