Android編譯過程總結及android中各種img檔案的作用以及系統啟動過程
本文以編譯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
2)repo初始化以及同步程式碼
$repo init [email protected]
在此過程中需要輸入名字和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
兩個主要的目錄為host和target,host表示主機(x86)生成的工具,target表示目標機執行的內容。
Host目錄的結構如下所示:
out/host/
|--common
| `--obj(JAVA庫)`--linux-x86
|--bin(二進位制程式)|--framework(JAVA庫,*.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)配置類
主要用來配置product、board,以及根據你的Host和Target選擇相應的工具以及設定相應的通用編譯選項:
-
-
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裡面主要定義了各種Host和Target結合的編譯器和編譯選項。
board主要是涉及到硬體晶片的配置,比如是否提供硬體的某些功能,或者晶片支援浮點運算等等。product針對當前的晶片配置來定義你將要生產產品的個性配置,只要指APK方面的配置,如哪些APK會包含在哪個product中,哪些APK在當前product中是不提供的。
這類檔案主要定義瞭如何來處理Module和Android.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來決定哪些本地模組會不會編譯進系統,通過PRODUCT和LOCAL_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這個檔案組織在一起,它定義了一個預設goals:droid,當我們在TOP目錄下敲Make實際上就等同於我們執行make droid。當Makeinclude所有的檔案,完成對所有make檔案的解析以後就會尋找生成droid的規則,依次生成它的依賴,直到所有滿足的模組被編譯好,然後使用相應的工具打包成相應的img。
4、make命令
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