最近研究了下Android 的编译系统,下面结合编译我们自己的产品 mobot 来对整个编译系统进行必要的介绍,方便大家今 后对默认编译的修改。

先列出几个觉得重要的Make 文件:

build/buildspec.mk

build/envsetup.sh

build/core/main.mk

build/core/envsetup.mk

build/core/config.mk

总的来说,Android 以模块 (module/package) 的形式来组织各个系统的部件,每个模块(module/package) 的目录下都会有一个 Android.mk 。所谓 module 就是指系统的 Native Code ,而相对于 Java 写的 Android application 称为 package 。

Makefile的主要流 程 1

初始化参数设置 2

读取Product 的设定 3

读取BoardConfig 4

读取所有Module 4

产生相应的Rules ,生成 image 5

具体make 操作: 6

完整编译 6

模块编译 6

单独编译image 文件 7

一些疑问和解答: 7

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 里,简单设置 几个主要编译路径的变量后,来到config.mk :

——————————————config.mk ——————————————

其中设置了源文件的一系列路径,包括头文件、库文件、服务、API 已经编译工具的路径。(前 36 行)

从40 行开始,定义一些编译模块的生成规则:

这里面除了第一个CLEAR_VARS 外,其他都对应的一种模块的生成规则,每一个 module 都会来 include 其中某个来生成目标模块。

例如:

Camera模块的 makefile 里( Android.mk )就包含了其中的一种生成规则BUILD_PACKAGE :

也就是Camera 会按照 package.mk 里的生成规则去生成目标模块。

回到config.mk ,接着会尝试读取 buildspec.mk 的设置:

如同注释所说,会尝试查找 buildspec.mk ,如果文件不 存在会自动使用环境变量的设置,如果仍然未定义,会按arm 默认的设置去 build 。

这里的buildspec.mk 可以自己创建,也可以将原先 build/ 下的 buildspec.mk.default 直接命名为buildspec.mk 并移到根目录。

实际上,buildspec.mk 配置都被屏蔽了,我们可以根据需要直接打开和修改一些变量。在这里我们可以加入自己的目标产品信息:

ifndef TARGET_PRODUCT

TARGET_PRODUCT:=mobot

endif

以及输出目录设置:

OUT_DIR:=$(TOPDIR)mobot

读取Product 的设定

回到config.mk ,接着进行全局变量设置,进入 envsetup.mk :

——————————————envsetup.mk ——————————————

里面的大部分函数都在build/envsetup.sh 中定义。

首先,设置版本信息,(15 行 ) 在 build/core/version_defaults.mk 中具体定义平台版本、 SDK版本、 Product 版本,我们可以将 BUILD_NUMBER 作为我们产品 mobot 的 version 信息,当然,也可以自定义一个版本变量。

回到envsetup.mk ,接着设置默认目标产品 (generic) ,这里由于我们在 buildspec.mk 里设置过TARGET_PRODUCT ,事实上这个 变量值为mobot 。

然后读取product 的设置 (135 行 ) , 具体实现在 build/core/ product_config.mk 中,进而进入product.mk ,从 build/target/product/ AndroidProducts.mk 中读出PRODUCT_MAKEFILES ,这些 makefile 各自独立定义 product ,而我们的产品 mobot 也应添加一个 makefile 文件 mobot.mk。在 mobot.mk 中我们可以加入所需编译的 PRODUCT_PACKAGES 。

下面为HOST 配置信息及输出目录,最后打印相关信息:

读取BoardConfig

接着回到config.mk , (114 行 ) 这 里会搜索所有的 BoardConfig.mk ,主要有以下两个地方:

$(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)/BoardConfig.mk

vendor/*/$(TARGET_DEVICE)/BoardConfig.mk

这里的TARGET_DEVICE 就是 mobot ,就是说为了定义我们自己的产品 mobot ,我们要在build/target/board 下添加一个自己的 目录 mobot 用来加载自己 的 board 配置。

在BoardConfig.mk 中会决定是否编译 bootloader 、 kernel 等信息。

读取所有Module

结束全局变量配置后,回到main.mk ,马上对编译工具及版本进行检查,错误便中断编译。

142行,包含文件 definitions.mk ,这里面定义了许多变量和函数供main.mk 使用。 main.mk第 446 行,这里会去读取所有的 Android.mk 文件:

include $(ONE_SHOT_MAKEFILE)

这个 ONE_SHOT_MAKEFILE 是在前面提到 的mm(envsetup.mk) 函数中赋 值的:

ONE_SHOT_MAKEFILE=$M make -C $T files $@

而M=$(findmakefile), 最终实现在:

回到main.mk ,最终将遍历查找到的所有子目录下的 Android.mk 的路径保存到subdir_makefiles 变量里 (main.mk 里的 470 行 ) :

我们在package/apps 下每个模块根目录都能看到 Android.mk ,里面会去定义当前本地模块的Tag : LOCAL_MODULE_TAGS ,Android 会通过这个 Tag 来决定哪些本地模块会编译进系统,通过PRODUCT 和 LOCAL_MODULE_TAGS 来决定哪些应用包会编译进系统。 ( 前面说 过,你也能通过buildspec.mk 来 制定你要编译进系统的模块 )

这个过 程在mian.mk 的 445 行开始,最后需要编译的模块路径打包到ALL_DEFAULT_INSTALLED_MODULES (602行 ) :

产生相应的Rules ,生成 image

所有需要配置的准备工作都已完成,下面该决定如何生成image 输出文件了,这一过程实际上在build/core/Makefile 中处理的。

这里定义各种img 的生成方式,包括 ramdisk.img 、 userdata.img 、 system.img 、 update.zip、 recover.img 等。具体对应的 rules 可以参考下图:

http://p.blog.csdn.net/images/p_blog_csdn_net/yili_xie/EntryImages/20091214/make%20goals.png

当Make include 所有的文件,完成对所有 make 文件的解析以后就会寻找生成 对应目标 的规则,依次生成它的依赖,直到 所有满足的模块被编译好,然后使用相应的工具打包成相应的img 。

具体make 操作:

完整编译

我们在根目录下输入make 命令即可开始完全编译。这个命令实际编译生成的默认目标是 droid:

也就是说,大家敲入make 实际上执行的 make droid 。而接下来大家看看 main.mk 文件里最后面的部分,会有很多伪目标,如 sdk 、 clean 、 clobber 等,这些在默认的 make droid 的命令下是不会执行的。我们可以在 make 后加上这些标签来单独实现一些操作。如:输入 make sdk  将会生成该版本对应的 SDK ,输入 make clean 会清除上次编译的输出。

模块编译

有时候我们只修改了某一个模块,希望能单独编译这个模块而不是重新完整编译一次,这时候我们要用到 build/envsetup.sh中提供的几个 bash 的帮助函数。

在 源代码根目录下执行:

.  build/envsetup.sh(.后面有空格 )

这 样大家相当于多了几个可用的命令。

这 时可以用help 命令查看帮助信息:

其中对模块编译有帮助的是tapas 、 m 、 mm 、 mmm 这几个命令。

1、 tapas——以交互方式设置 build 环境变量。

输入:tapas

第一步,选择目标设备:

第二步,选择代码格式

第三步,选择产品平台:

注意:这里,Google 源代码里默认是 generic ,而我们针对自己的产品应修改成 mobot

具体在build/envsetup.sh 里的函数 chooseproduct() 中对相应代码进行修 改。

2、 m、 mm 、 mmm 使用独立模块的 make 命令。

几个命 令的功能使用help 命令查看。

举个例 子,我们修改了Camera 模块的代码,现 在需要重新单独编译这一块,这时可以使用mmm 命令,后面跟指定模块的路径 ( 注意是模块的根目录 ) 。

具体如 下:

mmm packages/apps/Camera/

为了可 以直接测试改动,编译好后需要重新生成system.img

可以执 行:make snod

单独编译image 文件

一般我 们完整编译后,会生成三个重要的image 文 件: ramdisk.img 、 system.img 和userdata.img 。当然我们可以分开单独去编译 这三个目标:

make ramdisk —— ramdisk.img

make userdataimage —— userdata.img

make systemimage  —— system.img

一些疑问和解答:

1)  什么是recovery.img ?

顾名思义,recovery.img 是为了恢复系统的,相对于普通的 boot.img , recovery.img 多了一些图片文件 ( 恢复时界面的背景 ) 、 /sbin/recovery/ 目录 ( 跟 恢复有关的二进制文件 ) ,一 些初始化文件也不相同 (init.rc 、 init.goldfish.rc 、 default.prop)

这就是为什么启 动恢复模式时会进入类似文本界面而不是图形界面。

将recovery.img 文件复制到 SD 卡中,进入 shell 下输入:

mount -a

flash_image recovery /sdcard/recovery.img

若提示“no space on device ”,可用 fastboot 模式刷

fastboot erase recovery

fastboot flash recovery recovery.img

在关机状态下按home+power 键进入 recovery 模式,根据选项选择需要的操作。

2)  make sdk和 make droid 编译有什么不同?

make sdk:

其实,执行make sdk ,编译后会在目录 out/host/linux-x86 里生成 sdk 目录,这个 sdk 和官方下载的 sdk 包是一样的,可以直接使用。

Android 系统编译的更多相关文章

  1. H3 android 系统编译

    http://bbs.ickey.cn/group-topic-id-57981.html [Orange Pi PC试用体验]11编译android源码笔记 编译android和编译linux有点类 ...

  2. Android系统编译与测试

    1.Android系统分析 2.下载Android源代码(不包括Linux内核部分) 下载好了的Android_5.01.tar.gz,通过samba复制到ubuntu里,再解压之. 可以看到Andr ...

  3. Android系统编译时遇到的几个.mk的疑惑。

    在Android4.2的源代码Build/prduct_config.mk里面遇到几个疑惑: # Convert a short name like "sooner" into t ...

  4. Android系统编译环境及连接工具配置

    首先附上官网上关于环境搭建的地址:https://source.android.com/setup/build/initializing 官网目前建议的还是Ubuntu14.04,下面就是用的Ubun ...

  5. Android系统编译错误Note: Some input files use or override a deprecated API. 解决办法【转】

    本文转载自:http://blog.csdn.net/lilidejing/article/details/46564491 进入系统framework层修改了下MediaPlayer.java的源码 ...

  6. Android系统编译【转】

    本文转载自;http://blog.csdn.net/zirconsdu/article/details/8005415 Android编译系统分析 概要 由于android编译系统的复杂和使用了不熟 ...

  7. Android系统编译环境初始化时Product产品的import-nodes过程

    从运行make -f config,mk文件開始,config,mk作为当前的makefile文件.将会被make解析,一般make解析Makefile文件流程首先是载入当中include的各种其它m ...

  8. Android系统编译脚本理解

    android源码编译步骤: 1. repo sync 代码(下载代码) 2.start branch(用哪个分支,git相关) 3. 到根目录(android目录) $cd android/ 4. ...

  9. android系统编译打开系统蓝牙

    在项目配置文件ProjectConfig.mk中开启蓝牙以后,但是设置菜单中并没有出现蓝牙选项,最后发现是因为ProjectConfig.mk同级目录下没有蓝牙配置文件android.hardware ...

随机推荐

  1. jsonp原来是这么回事,豁然开朗

    什么是JSONP 先说说JSONP是怎么产生的: 其实网上关于JSONP的讲解有很多,但却千篇一律,而且云里雾里,对于很多刚接触的人来讲理解起来有些困难,小可不才,试着用自己的方式来阐释一下这个问题, ...

  2. Openjudge-计算概论(A)-分数求和

    描述: 输入n个分数并对他们求和,并用最简形式表示.所谓最简形式是指:分子分母的最大公约数为1:若最终结果的分母为1,则直接用整数表示. 如:5/6.10/3均是最简形式,而3/6需要化简为1/2, ...

  3. 37.看下图实现如下接口和类,并完成Adventure中的主方法。

    //接口Swim package jieKou; public interface ICanswim { void Swim(); } //接口Fly package jieKou; public i ...

  4. Shell grep 和正则

    在grep中正则有三种模式, 分别是基础(-G), 扩展(-E)和Perl(-P)模式 basic 模式 不支持\d, 支持\w \s \b. ?, +, {, |, (, and ) 在basic ...

  5. java集合概念

    Collection(单列集合) List(有序,可重复) ArrayList 底层数据结构是数组,查询快,增删慢 线程不安全,效率高 Vector 底层数据结构是数组,查询快,增删慢 线程安全,效率 ...

  6. grub引导centos

    下面来主要讲一下在grub下来引导centos: 其步骤如下; a   进入grub的命令模式. b  先熟悉一下grub  的一些命令 grub>help c  熟悉一下cat命令 d  ro ...

  7. linux重新部署mysql和tomcat时乱码问题

    mysql解决方法 vim /etc/my.cnf [client]default-character-set=utf8 [mysqld]default-storage-engine=INNODBch ...

  8. 笨方法学python--提示别人

    1 上次学到使用raw_input(), 还可以如下使用: age = raw_input("age?") 2 命令名查看raw_input的说明 unit, pydoc raw_ ...

  9. Canvas基础讲义

    今天先花点简单的篇幅和大家介绍下canvas. 1. 基本篇 1.1. 什么是 Canvas canvas 是 HTML5 提供的一个用于展示绘图效果的标签. canvas 原意画布, 帆布. 在 H ...

  10. postgresql删除属性

    PostgreSQL update and delete property from JSONB column up vote 2 down vote favorite From this artic ...