深刻淺出 - Android系統移植與平臺開發(五)- 編譯Android源碼(轉)

2.3編譯Android源碼

Android源碼體積很是龐大,由Dalvik虛擬機、Linux內核、編譯系統、框架代碼、Android定製C庫、測試套件、系統應用程序等部分組成,在編譯Android源碼以前,必需要先掌握Android源碼的組成。linux

2.3.1Android源碼目錄結構

在Android源碼中,按照不一樣功能代碼被放在不一樣的目錄下:android

 

目錄web

描述sql

bionicshell

針對Android系統定製的仿生標準C庫、連接器等所在目錄,Android系統並無使用Linux的glibc庫,bioinc C庫針對嵌入式系統作了優化,添加了一些Android特定的函數API同時大大減小庫的體積,也避免了LGPL版權的問題。數據庫

bootableapache

Android系統引導啓動代碼,用來引導系統、更新系統、恢復系統。windows

build瀏覽器

Android的編譯系統目錄,裏面包含大量的Makefile,用來編譯目標系統、Host主機開發環境等。bash

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以前,編譯系統須要加載一些編譯腳本命令到環境變量中,經過下面的指令來初始化編譯環境:

 

[cpp]  view plain  copy
 
 在CODE上查看代碼片派生到個人代碼片
  1. $ sourcebuild/envsetup.sh    

 

在執行完上述命令後,能夠經過執行help命令來查看全部加載的命令。

 

[cpp]  view plain  copy
 
 在CODE上查看代碼片派生到個人代碼片
  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.    
  12. Look at the source to view more functions. The complete list is:  
  13. 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源碼,能夠編譯出針對不一樣產品的系統。經過選擇一個目標編譯項,來決定編譯出針對哪一個產品的系統,咱們能夠經過執行下面的命令來選擇要編譯的目標系統:

 

[cpp]  view plain  copy
 
 在CODE上查看代碼片派生到個人代碼片
  1. $ lunch  
  2. You're building on Linux  
  3.    
  4. generic-eng simulator   
  5. Lunch menu... pick a combo:  
  6.      1. generic-eng  
  7.      2. simulator  
  8. Which would you like? [generic-eng]  

 

經過lunch命令可知,讓用戶輸入目標編譯項,咱們能夠選擇編譯項前的數字,也能夠直接輸入編譯項的名字。

…接前面終端輸出信息

 

[cpp]  view plain  copy
 
 在CODE上查看代碼片派生到個人代碼片
  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指令開始編譯目標系統:

 

[cpp]  view plain  copy
 
 在CODE上查看代碼片派生到個人代碼片
  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內核,咱們編寫了以下腳本,方便編譯。

 

[cpp]  view plain  copy
 
 在CODE上查看代碼片派生到個人代碼片
  1. $ cd /home/linux/android/android_source/kernel/goldfish/  
  2. $ vi build_kernel.sh  

 

添加以下內容:

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

 

[cpp]  view plain  copy
 
 在CODE上查看代碼片派生到個人代碼片
  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的路徑,讓它指向對應的交叉編譯器。

給腳本加上可執行權限,而後執行該腳本:

 

[cpp]  view plain  copy
 
 在CODE上查看代碼片派生到個人代碼片
  1. $ chmod a+x build_kernel.sh  
  2. $ ./build_kernel.sh  

 

內核編譯完成如圖x-x所示:

 

圖 內核編譯結果

 

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

相關文章
相關標籤/搜索