1. 程式人生 > >Android編譯過程總結及android中各種img檔案的作用以及系統啟動過程

Android編譯過程總結及android中各種img檔案的作用以及系統啟動過程

編譯環境:ubuntu 10.04(或者更高)(windows平臺目前不被支援)

本文以編譯android2.3為例,64位作業系統

1、編譯環境的準備

 (1)確保安裝有ubuntu系統或者虛擬機器

2)安裝JDK1.6(對於Android2.3以上程式碼)

$ sudo add-apt-repository "debhttp://archive.canonical.com/ lucid partner"

$ sudo add-apt-repository "deb-srchttp://archive.canonical.com/ubuntu lucid partner"

$ sudo apt-get update

$ sudo apt-get installsun-java6-jdk

3)安裝一些需要軟體包

$ sudo apt-get install git-coregnupg flex bison gperf build-essential \

zip curl zlib1g-dev libc6-devlib32ncurses5-dev ia32-libs \

x11proto-core-dev libx11-devlib32readline5-dev lib32z-dev \

libgl1-mesa-dev g++-multilibmingw32 tofrodos

4)安裝repo

$ git clonegit://android.git.kernel.org/tools/repo.git

$ mkdir ~/bin

$ cp repo-script/repo~/bin

$ vim ~/.bashrc,~/bin加入PARH環境變數,如:

$ exportPATH=~/bin:$PATH

儲存後,同步更新source~/.bashrc

5)設定git

執行以下語句
$git config --globaluser.name
"你的名字"
$git config --global user.email"
你的email地址"

(6)同步原始碼

1)建立工程目錄:
$ mkdir myandroid
$ cd myandroid

2repo初始化以及同步程式碼

$repo init [email protected]

:git庫名/manifest.git -b 主分支名

在此過程中需要輸入名字和email地址。初始化成功後,會顯示:repo initialized in /android
~/android下會有一個.repo的隱藏目錄

$repo sync(這一步會花費很長時間)

2、編譯

(1)注意事項

執行ls -la /bin/sh命令,如果輸出/bin/sh -> dash,

請執行$ sudo dpkg-reconfigure dash命令修改sh版本,並選擇“否”;

此處如果不改好的話,編譯時會出現錯誤。

(2)程式碼下載完成後就可以進行編譯了

$ cd myandroid

$ make(此過程需要很長時間)

(3)編譯完成後的程式碼結構

Android編譯完成之後,將會在根目錄下生成一個out資料夾,所有生成的內容均放在這個資料夾中。

Out資料夾的內容以及結構如下:

out/
|--CaseCheck.txt
|--casecheck.txt
|--host
||-- common
|`-- linux-x86
`--target
|--common
`--product

兩個主要的目錄為hosttargethost表示主機(x86)生成的工具,target表示目標機執行的內容。

Host目錄的結構如下所示

out/host/
|--common
| `--objJAVA庫)`--linux-x86
|--bin(二進位制程式)|--frameworkJAVA,.jar檔案)|--lib(共享庫*.so`--obj(中間生成的目標檔案)

host目錄是一些在主機上用的工具,有一些是JAVA的程式。

Target目錄的結構如下:

out/target/
|--common
| |--R(資原始檔)||-- docs
| `--obj(目標檔案)`--product
`--generic

其中common目錄表示通用的內容,product表示的產品的內容。

common目錄的obj中,包含兩個重要的目錄:

APPS:包含了JAVA應用程式生成的目標,每個應用程式對應其中的一個子目錄,將結合每個應用程式的原始檔案生成Android應用程式的APK包。

JAVA_LIBRARIES中包含了JAVA的庫,每個庫對應其中的一個子目錄。

在預設情況下,Android編譯將生成generic目錄,如果選定產品還可以生成其他的目錄(如ventana)。generic一般包含以下內容:

out/target/product/generic/
|--android-info.txt
|--clean_steps.mk
|--data
|--obj
|--ramdisk.img|--root
|--symbols
|--system
|--system.img|--userdata.img

generic/obj/APPS目錄中包含可各種JAVA應用,這與common/APPS想對應,但是已經打成了APK包。

system目錄是主要的檔案系統;data目錄是存放資料的檔案系統。

obj/SHARED_LIBRARIES中存放所有的動態庫;STATIC_LIBRARIES中存放所有的靜態庫。

img結尾的檔案是目標映像檔案,其中ramdisk.img是作為記憶體盤的根檔案系統映像,system.img是主要檔案系統的映像,userdata.img是資料內容映像。這幾個Image檔案是執行時真正需要的檔案。

(4)編譯單個模組

android中的一個應用程式可以單獨編譯,生成想對應的APK包,以Email為例。

$ sourcebuild/envsetup.sh

就多出一些命令:
- croot: Changes directory to the topof the tree.
- m: Makes from the top of thetree.
- mm: Builds all of the modules inthe current directory.
- mmm: Builds all of the modules inthe supplied directories.
- cgrep: Greps on all local C/C++files.
- jgrep: Greps on all local Javafiles.
- resgrep: Greps on all localres/*.xml files.
- godir: Go to the directorycontaining a file.

$ mm Email

編譯之後生成out/target/product/generic/system/app/Email.apk

3、編譯檔案分類

1)配置類

主要用來配置productboard,以及根據你的HostTarget選擇相應的工具以及設定相應的通用編譯選項:

config檔案

說明

build/core/config.mk

Config檔案的概括性說明

build/core/envsetup.mk

generate目錄構成等配置

build/target/product

產品相關配置

build/target/board

硬體相關的配置

build/core/combo

編譯選項配置

Config.mk是一個總括性的東西,它裡面定義了各種midule編譯所需要使用的HOST工具以及如何來編譯各種模組。envsetup.mk主要會讀取由envsetup.sh寫入環境變數中的一些變數來配置編譯過程中的輸出目錄,combo裡面主要定義了各種HostTarget結合的編譯器和編譯選項。

board主要是涉及到硬體晶片的配置,比如是否提供硬體的某些功能,或者晶片支援浮點運算等等。product針對當前的晶片配置來定義你將要生產產品的個性配置,只要指APK方面的配置,如哪些APK會包含在哪個product中,哪些APK在當前product中是不提供的。

這類檔案主要定義瞭如何來處理ModuleAndroid.mk,以及採用何種方式來生成目標模組,這些模組的規則都定義在config.mk裡面,如下:

CLEAR_VARS:=$(BUILD_SYSTEM)/clear_vars.mk

BUILD_HOST_STATIC_LIBRARY:=$(BUILD_SYSTEM)/host_static_library.mk

BUILD_HOST_SHARED_LIBRARY:=$(BUILD_SYSTEM)/host_shared_library.mk

BUILD_STATIC_LIBRARY:=$(BUILD_SYSTEM)/static_library.mk

BUILD_RAW_STATIC_LIBRARY :=$(BUILD_SYSTEM)/raw_static_library.mk

BUILD_SHARED_LIBRARY:=$(BUILD_SYSTEM)/shared_library.mk

BUILD_EXECUTABLE:=$(BUILD_SYSTEM)/executable.mk

BUILD_RAW_EXECUTABLE:=$(BUILD_SYSTEM)/raw_executable.mk

BUILD_HOST_EXECUTABLE:=$(BUILD_SYSTEM)/host_executable.mk

BUILD_PACKAGE:=$(BUILD_SYSTEM)/package.mk

BUILD_PHONY_PACKAGE:=$(BUILD_SYSTEM)/phony_package.mk

BUILD_HOST_PREBUILT:=$(BUILD_SYSTEM)/host_prebuilt.mk

BUILD_PREBUILT:=$(BUILD_SYSTEM)/prebuilt.mk

BUILD_MULTI_PREBUILT:=$(BUILD_SYSTEM)/multi_prebuilt.mk

BUILD_JAVA_LIBRARY:=$(BUILD_SYSTEM)/java_library.mk

BUILD_STATIC_JAVA_LIBRARY:=$(BUILD_SYSTEM)/static_java_library.mk

BUILD_HOST_JAVA_LIBRARY:=$(BUILD_SYSTEM)/host_java_library.mk

BUILD_DROIDDOC:=$(BUILD_SYSTEM)/droiddoc.mk

BUILD_COPY_HEADERS :=$(BUILD_SYSTEM)/copy_headers.mk

BUILD_KEY_CHAR_MAP :=$(BUILD_SYSTEM)/key_char_map.mk

除了CLEAR_VARS是清除本地變數之外,其他所有的都對應了一種模組的生成規則,每一個本地模組最後都會include其中的一種來生成目標模組。大部分上面的.mk都會包含base_rules.mk,這是對模組進行處理的基礎檔案。

3)單個模組的編譯

本地模組的Makefile檔案就是Android.mk檔案Android進行編譯的時候會通過下面的函式來遍歷所有子目錄中的Android.mk,一旦找到就不會再往層子目錄繼續尋找(所有你的模組定義的頂層Android.mk必須包含自己定義的子目錄中的Android.mk)

subdir_makefiles += \

$(shellbuild/tools/findleaves.sh--prune="./out" $(subdirs) Android.mk)

不同型別的本地模組具有不同的語法,但基本上是相通的,只有個別變數的不同。

Android通過LOCAL_MODULE_TAGS來決定哪些本地模組會不會編譯進系統,通過PRODUCTLOCAL_MODULE_TAGS來決定哪些應用包會編譯進系統,如果使用者不指定LOCAL_MODULE_TAGS,預設它的值是user。此外使用者可以通過buildspec.mk來指定你需要編譯進系統的模組。使用者也可以通過mm來編譯指定模組,或者通過make clean-module_name來刪除指定模組。

4)系統生成類

主要指build/core/Makefile檔案,這個檔案定義了生成各種img的方式,包括ramdisk.img, urerdata.img, system.img,recovery.img等。

所有的Makefile都通過build/core/main.mk這個檔案組織在一起,它定義了一個預設goalsdroid,當我們在TOP目錄下敲Make實際上就等同於我們執行make droid。當Makeinclude所有的檔案,完成對所有make檔案的解析以後就會尋找生成droid的規則,依次生成它的依賴,直到所有滿足的模組被編譯好,然後使用相應的工具打包成相應的img

4make命令

make clean刪除本次配置所編譯輸出的結果檔案。類似於:rm –rf./out/<configuration>

makeshowcommands:在編譯的時候顯示指令碼的命令,而不是顯示編譯的簡報。用於除錯指令碼

make:映像編譯成功後會在目錄~/android/src/out/target/product/generic下產生一些image檔案ramdisk.imgsystem.img userdata.img

首先通過編譯,先將android核心編譯成功。正常情況下,在目錄out/target.product/generic/(但是有的就沒有generic檔案,如freescale和iriver;但是lonshinetech下面就有這個檔案,依據情況而定,只要能找到生成的三個檔案就可以。例如:~/freescale/R9.2/out/target/product/imx51_bbg$)下會生成三個檔案:ramdisk.img,system.img,userdata.img。這三個檔案的作用如下:

(1)ramdisk.img
     一個分割槽影像檔案,它會在kernel 啟動的時候,以只讀的方式被 mount , 這個檔案中只是包含了 /init以及一些配置檔案,這個ramdisk 被用來呼叫init,以及把真正的root file system mount起來。
     #其實ramdisk.img的內容就是/out/target/product/generic/root目錄的壓縮而已。

 方法1:  android編譯生成後的ramdisk.img是一個gzip格式的檔案,輸入命令 #file ramdisk.img, 會得到 =>ramdisk.img: gzip compressed data, fromUnix

     那麼先解壓ramdisk.img,因為字尾不是.gz,所以用—S選項, # gunzip -S .imgramdisk.img
     這樣就得到一個新檔案ramdisk.img,用 # file ramdisk 檢視格式 , 得到 =>ramdisk: ASCII cpio archive (SVR4 with no CRC)

         可以看出解壓生成的ramdisk是cpio格式的檔案,再次解壓,為了防止解壓後文件混亂,
         首次建立一個目錄如: # mkdir rfs //rfs可以用來放ramdisk解壓後的檔案,  進入 # cd rfs
         解壓 # cpio -i -F ../ramdisk

  方法2:將ramdisk.img複製一份到任何其他目錄下,將其改名為ramdisk.img.gz,然後使用命令 # gunzipramdisk.img.gz,
        然後新建一個資料夾ramdisk,進入,輸入命令 # cpio -i -F ../ramdisk.img



      得到結果如下
   drwxr-xr-x  8 rootroot   4096 2011-01-12 11:36./
   drwxr-xr-x 13 rootroot   4096 2011-01-12 11:35../
   drwxrwx--x  2 rootroot   4096 2011-01-12 11:36data/
   -rw-r--r--  1 rootroot    1182011-01-12 11:36 default.prop
   drwxr-xr-x  2 rootroot   4096 2011-01-12 11:36dev/
   -rwxr-x---  1 root root 1077842011-01-12 11:36 init*
   -rwxr-x---  1 rootroot    4922011-01-12 11:36 init.freescale.rc*
   -rwxr-x---  1 rootroot   1677 2011-01-12 11:36init.goldfish.rc*
   -rwxr-x---  1 rootroot  18263 2011-01-12 11:36 init.rc*
   drwxr-xr-x  2 rootroot   4096 2011-01-12 11:36proc/
   drwxr-x---  2 rootroot   4096 2011-01-12 11:36sbin/
   drwxr-xr-x  2 rootroot   4096 2011-01-12 11:36sys/
   drwxr-xr-x  2 rootroot   4096 2011-01-12 11:36system/

 #可以看出這寫檔案是和root目錄下的內容完全一樣,其實就是對root目錄的打包和壓縮。可以是用tree -L1來檢視root的目錄

(2)system.img
     它包含了整個系統,android 的framework,application 等等,會被掛接到 "/"上,包含了系統中所有的二進位制檔案
    #system.img是out/target.product/generic/目錄下system目錄的一個對映,類似與根檔案系統的映像,放著android的應用程式、配置檔案和字型等。

   [email protected]:~/lonshinetech/src/SPU_B0_R0_0/out/target/product/generic/system$tree -L 1
   .
   |-- bin
   |-- build.prop
   |-- etc
   |-- fonts
   |-- framework
   |-- lib
   |-- usr
     -- xbin

重新打包system.img 具體辦法
 a)在android編譯後生成的out目錄中查詢這個工具 mkyaffs2image
   # find out/ -name mkyaffs2image
   得到=>out/host/linux-x86/bin/mkyaffs2image
 b)android編譯後會生成system/ 這個目錄,而這個目錄就是用來生成system.img的
  #  mkyaffs2image system/ system.img

(3)userdata.img

   將會被掛接到 /data 下,包含了所有應用相關的配置檔案,以及使用者相關的資料 。

(4)Android啟動過程


    Android啟動過程使,會由UBOOT傳入一個init引數,這個init引數制定了開機的時候執行的第一個執行的程式,預設就是init程式,這個程式就在ramdisk.img中,可以分析一下它的程式碼,看看在其中到底做了一些什麼樣的初始化任務,它的原始檔在system/core/init/init.c中。

   它會呼叫init.rc初始化這個檔案,這個檔案在out/target/product/generic/root下。
   android啟動時首先載入的是ramdisk.img映象,並掛載到/目錄下,並進行一系列的初始化動作,包括建立各種需要的目錄,初始化console,開啟服務等。system.img是在init.rc中指定一些指令碼命令,通過init.c進行解析並掛載到根目錄下的/system目錄下的。

相關推薦

Android編譯過程總結android各種img檔案作用以及系統啟動過程

編譯環境:ubuntu 10.04(或者更高)(windows平臺目前不被支援) 本文以編譯android2.3為例,64位作業系統 1、編譯環境的準備  (1)確保安裝有ubuntu系統或者虛擬機器 (2)安裝JDK1.6(對於Android2.3以上程式碼) $ sud

Android 編譯錯誤總結收集

收集和遇到的部分error,先記錄如下,改天按照建立android及使用情景分類整理。以後遇到的在慢慢新增進來 1.編譯錯誤: “/usr/bin/ld:cannotfind -lz” 解決方法: 需要安裝zlib-dev這個包,線上安裝命令為:apt-getinst

android 編譯錯誤總結--使用ButterKnife

1.Android Studio使用ButterKnife各種錯誤解決Plugin with id 'android-apt' not found.   ButterKnife可以幫助我們查詢控制元件,新增事件繫結等等,可以減少很多程式碼,但是在使用過程中對新手來說,往往會碰到很多

Android 年底面試總結未來兩年規劃

        面試是每個求職者永恆的話題,在這個資本寒冬的冬天,跳槽變得越來越謹慎了,但是,有時候為了一份自己滿意的工作還是要勇敢的跳出來。不管是因為和上級不和還是因為你要過圖輕鬆然後幡然悔悟,總之,打工者就是這麼回事。下面分享下年底面試的經歷。這個過程,真的不短,要準備

Android資原始檔各種XML的作用與解釋

眾所周知,XML是一種可擴充套件標記語言,它被用來傳輸和儲存資料。在Android中也會隨處可見XML檔案,包括一個android專案不可缺少的AndroidManifest.xml清單檔案,res資

Android 混淆程式碼總結Android APK反編譯(最新更新)

http://blog.csdn.net/vipzjyno1/article/details/21039349/ http://blog.csdn.net/vipzjyno1/article/details/21039349/  反編譯 在學習Android開發的過程你

React Native 之Android混合開發,遇到的各種

最近自己也是剛在學習React Native的知識,在學習到React Native 嵌入到原生應用的時候,感覺遇到了各種坑,這裡做一下記錄。若有說得不對的地方,謝謝大家糾正。 React Native嵌入到原生應用的教程在其官方指導文件裡也有,但是感覺很多注意點沒講到,現

MTK Android 編譯模組說明編譯命令

alps/檔案目錄 [makeMtk]   ALPS project make /build entry point. [bionic]   C runtime libraries, such as, libc, libm, libdl, dynamic linker et

Android ViewTreeObserver使用總結獲得View高度的幾種方法

ViewTreeObserver 註冊一個觀察者來監聽檢視樹,當檢視樹的佈局、檢視樹的焦點、檢視樹將要繪製、檢視樹滾動等發生改變時,ViewTreeObserver都會收到通知,ViewTreeObserver不能被例項化,可以呼叫View.getViewTre

阿里雲ECS架設VPN(pptp)過程總結安全策略設定

在架設VPN之前參考了網上大量的搭建教程,但是實際操作時還是遇到很多問題,在此把安裝的步驟和問題都列出來,希望能幫到各位。 一、環境 伺服器提供商:阿里雲ECS雲伺服器 作業系統: CentOS 7.2 64位 1、先看看你的主機是否支援pptp,返回結果為yes就表示通過

Android 面試題總結Android 基礎(一)

Android 面試題總結之Android 基礎Activity(一) 轉眼間畢業好久了,寫程式也很久了,從高中就一直寫到現在好多年了啊,學習了很多東西,把之前整理的資料和知識點慢慢分享出來。這裡主要總結Android可能出的面試的題目比較全面\詳細,持

Android 面試題總結Android 基礎(三)

Android 面試題總結之Android 基礎Broadcast Receiver(三) 在上一章節Android 面試題總結之Android 基礎ContentProvider(二) 我們講的ContentProvider和Intent基礎知識。本節

Android知識體系總結Android部分之冷啟動&熱啟動

Android知識體系總結之Android部分之冷啟動&熱啟動篇 1.冷啟動&熱啟動 1.1 什麼是冷啟動?   當啟動應用時,後臺沒有該應用的程序,這時系統會重新建立一個新的程序分配給該應用,這個啟動方式就是冷啟動。它的特點就是冷啟動因為系統

Android提高與總結Android技能導圖

自己根據自己所涉及的一些知識點總結的Android技能圖。大體涉及了Android應用開發較全面的重要的技術點! 另附技能導圖 圖片網址 !太小可以點選這裡 個人總結: 學

Android Studio 權威教程]AS 配置強大的版本管理系統(Git、SVN、等)

在Eclipse中新增Git等版本管理工具需要自己新增外掛,而且個人覺得不咋好用,在AS中已經給我們整合好了,我們只需要配置一下就OK了,今天就和大家聊聊怎麼配置以及使用的要點。 1. 安裝Git/CVS 第一步首先你需要安裝Git/CVS

android原始碼4.4.2----系統啟動過程分析

public class SystemServer {   private static final String TAG = "SystemServer";   public static final int FACTORY_TEST_OFF = 0;   public static final int F

Android系統啟動過程-uBoot+Kernel+Android

轉載自:http://www.cnblogs.com/pngcui/p/4665106.html 摘要:本文是參考大量網上資源在結合自己檢視原始碼總結出來的,讓自己同時也讓大家加深對Android系統啟動過程有一個更加深入的瞭解!再次強調,本文的大多數功勞應

Mac OS 下手動編譯靜態庫Xcode使用該靜態庫的例子(一)

第一部分 Mac OS 下建立靜態庫 前言 眾所周知,Mac OS實際上是基於UNIX來編寫的,因此它保留了眾多的UNIX原有的特性,就靜態庫而言,仍舊以libXXXX.a來命名。要編譯Mac下的靜態庫,方法有很多,如使用Xcode的建立和編譯,也可以直接使用命令列(可結合

Android 面試題總結Android 進階(二)

Android 之美 從0到1 之Android 進階(二) 在上一章節中《Android 之美 從0到1 之Android 進階(一)》中我們已經理解了一些View的基本知識並且知道如何自定義View。那麼本章節將繼續深入理解View,關於View的繪

Android原始碼學習之八—系統啟動過程

Android原始碼數量龐大,雖然對它的學習從未停止,但是整理成這樣的文字,實在是費時費力的一件事情,不過好在前文已經對其基本機制加以分析,相信以此為基礎,其他的內容學習起來就沒那麼困難了。 今天是20