2.3编译Android源码

Android源码体积非常庞大,由Dalvik虚拟机、Linux内核、编译系统、框架代码、Android定制C库、测试套件、系统应用程序等部分组成,在编译Android源码之前,必须要先掌握Android源码的组成。

2.3.1Android源码目录结构

在Android源码中,按照不同功能代码被放在不同的目录下:

目录

描述

bionic

针对Android系统定制的仿生标准C库、链接器等所在目录,Android系统并没有使用Linux的glibc库,bioinc C库针对嵌入式系统做了优化,添加了一些Android特定的函数API同时大大减少库的体积,也避免了LGPL版权的问题。

bootable

Android系统引导启动代码,用来引导系统、更新系统、恢复系统。

build

Android的编译系统目录,里面包含大量的Makefile,用来编译目标系统、Host主机开发环境等。

cts

兼容性测试工具目录。

dalvik

Dalvik虚拟机,Android系统得以运行的虚拟执行环境。

development

程序开发所需要的模板和工具。

external

Android系统使用的其它开源代码目录,如jpeg图片解码开源库、opencore开源代码等。

frameworks

框架层代码,frameworks/base目录下存放目标系统的框架库,frameworks/policies/base下存放应用程序框架代码。

hardware

HAL(Hardware Abstraction Layer)硬件抽象层代码。

kernel

Linux内核目录,默认下载的Android源码里没有,需单独下载。

packages

Android系统级应用程序源码目录,如摄像应用、电话应用等。

prebuilt

主机编译工具目录,如arm-linux-gcc交叉系统工具链等。

sdk

SDK及模拟器。

system

init进程、蓝牙、无线WIFI工具、uevent进程目录。

devices

厂商设备配置目录,针对不同设备,由不同的子目录来分别管理,用来裁剪实现不同设备上Android目标系统。

在external目录下存放着大量的外部开源代码:

外部开源项目

描述

外部开源项目

描述

aes

AES加密

libxml2

xml解析库

apache-http

网页服务器

make

asm

netbeans-visual

bluez

蓝牙相关、协议栈

netcat

simple Unix utility which reads and writes dataacross network connections

ccache

netperf

网络性能测量工具

clearsilver

neven

看代码和JNI相关

dbus

低延时、低开销、高可用性的IPC机制

opencore

多媒体框架

dhcpcd

DHCP服务

openssl

SSL加密相关

dropbear

SSH2的server

oprofile

OProfile是Linux内核支持的一种性能分析机制

eclipse

ppp

pppd拨号命令,好像还没有chat

elfcopy

复制ELF的工具

protobuf

a flexible, efficient, automated mechanism for serializing structured data

elfutils

ELF工具

qemu

arm模拟器

embunit

Embedded Unit Project

safe-iop

functions for performing safe integer operations

emma

Java代码覆盖率统计工具

sdl

esd

Enlightened Sound Daemon,将多种音频流混合在一个设备上播放

skia

skia图形引擎

expat

Expat is a stream-oriented XML parser

sonivox

sole MIDI solution for Google Android Mobile Phone Platform

fdlibm

FDLIBM (Freely Distributable LIBM)

sqlite

数据库

Flex

srec

Nuance 公司提供的开源连续非特定人语音识别

freetype

字体库

strace

trace工具

gdata

google的无线数据相关

swing-worker

diflib

swt

googleclient

google用户库

tagsoup

TagSoup是一个Java开发符合SAX的HTML解析器

icu4c

ICU(International Component for Unicode)在C/C++下的版本

tcpdump

抓TCP包的软件

iptables

防火墙

tinyxml

TinyXml is a simple, small, C++ XML parser

Jdiff

generate a report describing the difference between two public Java APIs

toolchain

jfreechart

tremor

I stream and file decoder provides an embeddable,integer-only library

jpeg

jpeg库

webkit

浏览器核心

kxml2

wpa_supplicant

无线网卡管理

libffi

libffi is a foreign function interface library.

yaffs2

yaffs文件系统

libpcap

网络数据包捕获函数

zlib

a general purpose data compression library

在packages/app目录下存放着大量系统级应用程序,我们可以拿到这些应用程序代码分析、理解,编写出效率更高,性能更好的应用:

系统应用程序

描述

AlarmClock

闹钟

Browser

浏览器

Calculator

计算器

Calendar

日历

Camera

摄像头

Contacts

联系人

Email

邮件

GoogleSearch

Google搜索

HTML Viewer

浏览器附属界面,被浏览器应用调用,同时提供存储记录功能

IM

即时通讯,为手机提供信号发送、接收、通信的服务

Launcher

Android的桌面

Mms

彩信业务

Music

音乐播放器

PackageInstaller

应用程序安装、卸载器

Phone

电话应用

Settings

系统设置

SoundRecorder

录音机

Stk

短信接收和发送

Sync

同步数据

Updater

更新

VoiceDialer

语音识别通话

在package/providers目录下存放的是系统级内容提供器(Content Provider):

系统内容提供器

描述

CalendarProvider

日历提供器

ContactsProvider

联系人提供器

DownloadProvider

下载管理提供器

DrmProvider

DRM受保护数据存储服务,创建和更新数据库时调用

GoogleContactsProvider

谷歌联系人提供器

GoogleSubscribedFeedsProvider

Google同步功能

ImProvider

即时通讯提供器

MediaProvider

媒体提供器、提供存储数据

SettingsProvider

系统设置提供器

SubscribedFeedsProvider

TelephonyProvider

彩信提供器

2.3.2编译Android

按照Android官方网站给出的步骤,编译Android源码过程如下:

Ø 初始化编译环境

在编译Android之前,编译系统需要加载一些编译脚本命令到环境变量中,通过下面的指令来初始化编译环境:

  1. $ sourcebuild/envsetup.sh

在执行完上述命令后,可以通过执行help命令来查看所有加载的命令。

  1. $ help
  2. Invoke ". build/envsetup.sh" from your shell to add the following functions to your environment:
  3. - croot:   Changes directory to the top of the tree.
  4. - m:       Makes from the top of the tree.
  5. - mm:      Builds all of the modules in the current directory.
  6. - mmm:     Builds all of the modules in the supplied directories.
  7. - cgrep:   Greps on all local C/C++ files.
  8. - jgrep:   Greps on all local Java files.
  9. - resgrep: Greps on all local res/*.xml files.
  10. - godir:   Go to the directory containing a file.
  11. Look at the source to view more functions. The complete list is:
  12. add_lunch_combo cgrep check_product check_variant choosecombo chooseproduct choosetype choosevariant cproj croot findmakefile gdbclient get_abs_build_var getbugreports get_build_var getprebuilt gettop godir help isviewserverstarted jgrep lunch m mm mmm pid printconfig print_lunch_menu resgrep runhat runtest setpaths set_sequence_number set_stuff_for_environment settitle smoketest startviewserver stopviewserver systemstack tapas tracedmdump

常用脚本命令:

脚本命令

描述

Help

帮助信息,打印所有命令

add_lunch_combo

添加新目标编译项

print_lunch_menu

打印所有目标编译项

lunch

选择目标编译项

m

从源码树顶级目录向下编译源码,相当于执行make

mm

从当前目录向下编译源码

mmm

从指定目录向下编译源码,通常用来编译某个模块

cgrep

从所有的C,C++文件里查找指定字符串

jgrep

从所有的Java文件里查找指定字符串

Ø 选择编译选项

由于Android源码是一个开源的系统,然要匹配很多设备产品,也就是说一个版本的Android源码,可以编译出针对不同产品的系统。通过选择一个目标编译项,来决定编译出针对哪个产品的系统,我们可以通过执行下面的命令来选择要编译的目标系统:

  1. $ lunch
  2. You're building on Linux
  3. generic-eng simulator
  4. Lunch menu... pick a combo:
  5. 1. generic-eng
  6. 2. simulator
  7. Which would you like? [generic-eng]

通过lunch命令可知,让用户输入目标编译项,我们可以选择编译项前的数字,也可以直接输入编译项的名字。

…接前面终端输出信息

  1. Which would you like? [generic-eng]1 [回车]
  2. ============================================
  3. PLATFORM_VERSION_CODENAME=REL
  4. PLATFORM_VERSION=2.1-update1
  5. TARGET_PRODUCT=generic
  6. TARGET_BUILD_VARIANT=eng
  7. TARGET_SIMULATOR=false
  8. TARGET_BUILD_TYPE=release
  9. TARGET_ARCH=arm
  10. HOST_ARCH=x86
  11. HOST_OS=linux
  12. HOST_BUILD_TYPE=release
  13. BUILD_ID=ERE27
  14. ============================================

由上面结果可知,当用户输入:1或generic-eng时,会打印出上面的信息,这些信息是Android的编译系统必须依赖的环境变量,只有设置了这些变量,才能决定Android系统如何编译,编译成什么平台,编译成什么版本。

目标编译项格式:产品名-版本变量名,目标编译项可以由用户添加(见xxx章节),产品名是目标设备的产品名,由厂商自己定义,generic产品是通用产品,它是Android默认设备的产品名,它包含了常用的手机的所有功能,自己定义的产品可以继承generic,并重写它的功能,达到定制产品的目的(见xxx章节)。

版本变量名由以下几个组成:

  • eng:工程版本,
  • user:最终用户版本
  • userdebug:调试版本
  • tests:测试版本

其中,eng版本产品其实就是手机行业的工程机,它不是最终销售的产品,而是产品在定型下线之前放出的一些测试用机器,用于检测和标准的认证,这些工程机上安装的系统为eng版本,user是最终用户机发行版本,userdebug是调试版本,它比用户机添加了一些调试功能,如adb调试默认打开等,tests测试版本,该版本会安装一些测试程序,用于测试系统。

上述四种版本的分类作用,其一:用于区分目标系统里的所有的应用程序、库、测试程序等,将它们打上对应的Tags,当选择一个版本编译时,拥有对应Tags及低级别的Tags的程序会被编译安装到目标设备上,应用程序Tags的包含关系如下图:。其二:根据不同的版本,系统会有不同的设置,如adbd在用户版本里是关闭的,在其它版本中是默认打开的,ro.secure属性用户版本值为1,其它版本为0。

Ø 编译源码

执行完前面的命令后,我们可以输入make指令开始编译目标系统:

  1. $make

编译的时长与机器的硬件配置有关系,当第一次编译时一般需要数小时以上。后续编译,相对快多了,编译完的效果如下图所示:

通过上面的输出信息可知,Android系统编译完后,在out/target/product/generic/目录下产出了三个文件:system.img、ramdisk.img、userdata.img。

  • system.img:android系统的文件系统,里面包含了android系统的应用程序(apk),系统用到的各种库(jar, so)和资源,配置文件(etc目录下),系统命令(bin,usr/bin, xbin),该映像文件是由out/target/product/generic/system目录打包生成的,我们可以对这个目录里的东西进行定制化,比如,你要想让android系统默认安装一个应用程序,那么可以将要安装的apk文件拷贝到out/target/product/generic/system/app目录下。
  • userdata.img:用户数据映像,里面包含有程序安装信息等,好比如是windows的C:/Program Files/目录。
  • ramdisk.img:内存磁盘映像。linux内核启动起来,要挂载一个文件系统作为自己的根文件系统,里面含有Linux内核启动过程中依赖的一些程序和配置文件。ramdisk.img就是一个最小化的根文件系统,它被加载到内存中作为Android的根文件系统。该映像是由out/target/product/generic/root目录打包生成的。前面所述的userdata.img和system.img映像,在linux系统启动起来后挂载到ramdisk.img中的data,system目录下。

其实,Android手机的ROM包(通常为update.zip文件),就是主要由上述三个映像文件构成的:

ROM包文件

说明

android-info.txt

ROM版本及刷写配置信息

boot.img

Linux内核zImage、ramdisk.img

system.img

Android系统映像

userdata.img

用户数据映像

其它映像

只要我们拿到手机的源码,就可以自己编译出自己的ROM,不过,一般手机厂商不会开源自己产品源码,都是第三方爱好者自己下载,修改编译的,如:业界著名的CM团队:http://www.cyanogenmod.com/

由于完全编译Android系统耗时很长,并且Android源码由很多模块组成,我们可以通过下面一些编译命令来减少编译时间:

编译命令

说明

make snod

打包生成system.img,不检查依赖关系

make bootimage

打包生成ramdisk.img

mmm

指定编译某个目录下的模块

上述三个命令经常在我们源码开发时使用,希望大家记住。

2.3.3编译Linux内核

Android使用Linux内核,在源码级开发过程中,有时要修改内核代码,通常内核代码是和目标设备相关的,我们使用的是模拟器的内核,即使没有硬件设备也可以完成实验。

编译Android的内核,需要用到交叉编译器,我们可以直接使用Android源码里自带的arm-eabi-gcc编译器,为了编译出针对模拟器的内核(模拟器的CPU为Goldfish),还要配置内核(如果不知道如何配置内核,请读者阅读内核裁剪相关资料),为了方便我们编译Goldfish内核,我们编写了如下脚本,方便编译。

  1. $ cd /home/linux/android/android_source/kernel/goldfish/
  2. $ vi build_kernel.sh

添加如下内容:

@ /home/linux/android/android_source/kernel/goldfish/build_kernel.sh

  1. #!/bin/bash
  2. export PATH=/home/linux/android/android_source/prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin:$PATH
  3. export ARCH=arm
  4. export SUBARCH=arm
  5. export CROSS_COMPILE=arm-eabi-
  6. if [ ! –f .config ] ; then
  7. make goldfish_armv7_defconfig
  8. fi
  9. make

注:当Andorid源码目录发生改变时,要修改PATH的路径,让它指向对应的交叉编译器。

给脚本加上可执行权限,然后执行该脚本:

  1. $ chmod a+x build_kernel.sh
  2. $ ./build_kernel.sh

内核编译完成如图x-x所示:

图 内核编译结果

转自:http://blog.csdn.net/mr_raptor/article/details/20934501

深入浅出 - Android系统移植与平台开发(五)- 编译Android源码(转)的更多相关文章

  1. 深入浅出 - Android系统移植与平台开发(一)

    深入浅出 - Android系统移植与平台开发(一) 分类: Android移植2012-09-05 14:16 16173人阅读 评论(12) 收藏 举报 androidgitgooglejdkub ...

  2. 深入浅出 - Android系统移植与平台开发(五)- 定制手机模拟器ROM

    一. 修改化定制Android4.0系统 Android系统启动时,先加载Linux内核,在Linux的framebuffer驱动里可以定制开 机界面,Linux内核启动成功后,挂载根文件系统,启动A ...

  3. 深入浅出 - Android系统移植与平台开发(三)- 编译并运行Android4.0模拟器

    作者:唐老师,华清远见嵌入式学院讲师. 1.   编译Android模拟器 在Ubuntu下,我们可以在源码里编译出自己的模拟器及SDK等编译工具,当然这个和在windows里下载的看起来没有什么区别 ...

  4. 深入浅出 - Android系统移植与平台开发(二) - 准备Android开发环境

    作者:唐老师,华清远见嵌入式学院讲师. 编译Android源码 关于android系统的编译,Android的官方网站上也给出了详细的说明.http://source.android.com/sour ...

  5. 深入浅出-Android系统移植与平台开发(一)- Android4.0系统的下载与编译

    作者:唐老师,华清远见嵌入式学院讲师. 一.Android4.0系统的下载与编译 Android系统的下载与编译,Google的官方网站上已经给出了详细的说明,请参照Android的官方网址: htt ...

  6. 深入浅出 - Android系统移植与平台开发(十)- Android编译系统与定制Android平台系统(瘋耔修改篇二)

    第四章.Android编译系统与定制Android平台系统 4.1Android编译系统 Android的源码由几十万个文件构成,这些文件之间有的相互依赖,有的又相互独立,它们按功能或类型又被放到不同 ...

  7. 深入浅出 - Android系统移植与平台开发(十一)- Android系统的定制(瘋耔修改篇一)

    首先非常感谢原文作者为我们提供的知识库,因为有你们的贡献,我们的开发难度更显简单 原文 :   http://blog.csdn.net/mr_raptor/article/details/30113 ...

  8. 深入浅出 - Android系统移植与平台开发(十二)- Android JNI机制

    第五章.JNI机制 4.1 JNI概述 由前面基础知识可知,Android的应用层由Java语言编写,Framework框架层则是由Java代码与C/C++语言实现,之所以由两种不同的语言组合开发框架 ...

  9. 深入浅出 - Android系统移植与平台开发(六)- 为Android启动加速

    作者:唐老师,华清远见嵌入式学院讲师. Android的启动速度一直以来是他的诟病,虽然现在Android设备的硬件速度越来越快,但是随着新 版本的出现,其启动速度一直都比较慢,当然,作为程序员,我们 ...

随机推荐

  1. [CareerCup] 7.6 The Line Passes the Most Number of Points 经过最多点的直线

    7.6 Given a two-dimensional graph with points on it, find a line which passes the most number of poi ...

  2. 信息安全系统设计基础实验一:Linux开发环境的配置和使用(20135234,20135229)

    http://www.cnblogs.com/mqy123/p/4968386.html

  3. EF实体框架之CodeFirst六

    上午的时候把复杂类型学习了一下,想着趁着周六日把Code First学习完,所以下午还是把Code First中的关系学习下.在数据库中最重要的恐怕就是E-R图了,E-R体现了表与表直接的关系.使用C ...

  4. [C#基础]ref和out的区别

    在C#中通过使用方法来获取返回值时,通常只能得到一个返回值.因此,当一个方法需要返回多个值的时候,就需要用到ref和out,那么这两个方法区别在哪儿呢? MSDN:       ref 关键字使参数按 ...

  5. 第四十六课:MVC和MVVM的开发区别

    实现MVC的目的就是为了让M和V相分离.前端的MVC无法做到View和Model的相分离,而MVVM可以. 我们先来看一个用MVC模式开发的经典例子:(一定要深入了解这种开发的思想,而不是看懂代码) ...

  6. MVC——应用Ajax获取不到数据问题解答

    当我们使用控制器利用Ajax获取表单数据时,调试为null,这时看看你接受表单时定义的参数名字是否为action 其实不能起这个名字的,这个名字和控制器关键字冲突了 随便换个其它名字就好了,比如我起个 ...

  7. java多线程-BlockingQueue

    BlockingQueue简介 ArrayBlockingQueue:基于数组实现的一个阻塞队列,在创建ArrayBlockingQueue对象时必须制定容量大小.并且可以指定公平性与非公平性,默认情 ...

  8. publish_subscribe

    <!DOCTYPE html> <html> <head> <title></title> </head> <body&g ...

  9. 常用的Java 架包(jar)的用途

    前言:如果需要在项目中引入jar包,可以采用maven,配置方式在 http://mvnrepository.com 查询  slf4j-api 简介:slf4j并不是一种具体的日志系统,而是一个用户 ...

  10. BZOJ-1879 Bill的挑战 状态压缩DP

    MD....怎么又是状压....... 1879: [Sdoi2009]Bill的挑战 Time Limit: 4 Sec Memory Limit: 64 MB Submit: 537 Solved ...