日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

深入浅出

發布時間:2023/12/15 综合教程 22 生活家
生活随笔 收集整理的這篇文章主要介紹了 深入浅出 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

第四章、Android編譯系統與定制Android平臺系統

4.1Android編譯系統

Android的源碼由幾十萬個文件構成,這些文件之間有的相互依賴,有的又相互獨立,它們按功能或類型又被放到不同目錄下,對于這個大的一個工程,Android通過自己的編譯系統完成編譯過程。

4.1.1 Android編譯系統介紹

Android和Linux一樣,他們的編譯系統都是通過Makefile工具來組織編譯源碼的。Makefile工具用來解釋和執行Makefile文件,在Makefile文件里定義好工程源碼的編譯規則,通過make命令即可以完成對整個工程的自動編譯。因此分析makefile文件是理解編譯系統的關鍵。

在Android中,下面幾個主要的makefile文件構成了Android編譯系統。

圖x-x Android編譯系統組成

①Makefile:編譯系統的入口Makefile文件,它只有一行代碼,包含build/core/main.mk

②build/core/main.mk:主要Makefile,定義了Android編譯系統的主線

③build/core/config.mk:根據用戶輸入的編譯選項導出配置變量,影響編譯目標

④build/core/envsetup.mk:定義大量全局變量,用戶編譯配置

⑤build/core/product_config.mk:根據用戶選擇的目標產品,定義編譯結果輸出目錄

⑥device/*/$(TARGET_DEVICE)/BoardConfig.mk:根據用戶選擇的目標產品找到對應的設備TARGET_DEVICE,加載設備的板級配置

⑦build/core/definitions.mk:定義編譯過程中用到的大量變量和宏,是編譯系統的函數庫

⑧MODULES_DIR/Android.mk :每個模塊的規則定義文件,它出現在每個要編譯的目錄下,如圖x-x所示,我們可以自己向Android系統中添加自己的模塊,來達到定制系統的目的。

圖x-x 模塊中的Android.mk文件

⑨build/core/Makefile:Android編譯目標規則定義文件,最終編譯結果在該文件中定義,如system.img、ramdisk.img、boot.img、userdata.img等

4.1.2 Android.mk文件

在Android源碼中,大量的源碼按照功能通過目錄來分類,同一功能的代碼通常被編譯成一個目標文件,目標文件不僅僅包含可執行C/C++應用程序,還包含動態庫、靜態庫、Java類庫、Android應用程序等,在Android編譯系統中,每個被編譯的目標文件被稱為一個模塊(module),在每個模塊的源碼目錄中必須創建一個Android.mk文件作為編譯規則,這些Android.mk文件在編譯時被編譯系統中的findleaves.py腳本包含進去。

@build/core/main.mk

489 subdir_makefiles :=

490$(shell build/tools/findleaves.py --prune=out --prune=.repo --prune=.git$(subdirs) Android.mk)

491

492 include $(subdir_makefiles)

注:findleaves.py由Python語言編譯的腳本,Python是一種執行效率比較高的面向對象的腳本,上述腳本意思是返回subdirs目錄下的Android.mk文件,但是會跳過out、.reop、.git目錄。

通常編譯一個模塊時編譯器需要知道以下內容:

Ø編譯什么文件?(指定源碼目錄和源碼文件)

Ø編譯器需要哪些編譯參數?

Ø編譯時需要哪些庫或頭文件?

Ø如何編譯?(編譯成動態庫、靜態庫、二進制程序、Android應用還是Java庫?)

Ø編譯目標

Android.mk的語法不同于Makefile,Android.mk語法更簡潔,用戶只需在Android.mk中定義出一些編譯變量,Android的編譯系統會根據Android.mk文件中變量的值進行編譯。

比如Zygote進程app_process模塊中的Android.mk如下面代碼所示:

@ frameworks/base/cmds/app_process/Android.mk

1LOCAL_PATH:= $(call my-dir) #指定源碼目錄

2include $(CLEAR_VARS) #包含清除編譯變量的mk文件,防止影響本次編譯

3

4LOCAL_SRC_FILES:= #指定被編譯源碼

5 app_main.cpp

6

7LOCAL_SHARED_LIBRARIES := #指定編譯Zygote時用到的其它動態庫

8 libcutils

9 libutils

10 libbinder

11 libandroid_runtime

12

13LOCAL_MODULE:= app_process #指定被編譯模塊的名字

14

15include $(BUILD_EXECUTABLE) #指定編譯方式,編譯成可執行程序

再比如Camera應用程序中的Android.mk:

@ packages/apps/Camera/Android.mk

1LOCAL_PATH:= $(call my-dir) #指定源碼目錄

2include $(CLEAR_VARS) #包含清除編譯變量的mk文件,防止影響本次編譯

3

4LOCAL_MODULE_TAGS := optional #指定應用程序標簽

5

6LOCAL_SRC_FILES := $(call all-java-files-under, src) #指定被編譯源碼

7

8LOCAL_PACKAGE_NAME := Camera #指定Android應用程序名

9LOCAL_SDK_VERSION := current #指定該應用程序依賴的SDK版本

10

11LOCAL_PROGUARD_FLAG_FILES := proguard.flags #指定混淆編譯配置文件

12

13include $(BUILD_PACKAGE) #指定模塊編譯方式,這兒編譯成Android應用程序

14

15 # Usethe following include to make our test apk.

16include $(call all-makefiles-under,$(LOCAL_PATH)) # 包含當前目錄下子目錄中的Android.mk文件,向下編譯

通過上面兩個例子可以看出來,Android.mk文件結構很簡單,每個模塊的Android.mk文件必須完成以下操作:

Ø指定當前模塊的目錄

通過調用$(call my-dir)命令包(一些Makefile的集合),來獲得當前模塊目錄。

Ø清除所有的LOCAL_XX變量

通過include命令包含clear_vars.mk文件來清除所有的LOCAL_XX變量,防止影響本次編譯結果,clear_vars.mk文件由變量CLEAR_VARS來定義

Ø指定源碼文件

通過LOCAL_SRC_FILES變量指定源碼文件,對于C/C++文件,要將它們全部列出來賦值給LOCAL_SRC_FILES(見上面程序代碼),對于Java源碼,可以通過調用命令包$(callall-java-files-under, src)來實現,它會在src目錄下查找所有的Java文件,將其羅列出來。

Ø指定編譯細節

在編譯時可能需要修改編譯器參數、需要鏈接其它的庫、需要其它路徑下的頭文件等編譯細節。

Ø指定目標模塊名

如果是C/C++庫、可執行程序或Java類庫,通過LOCAL_MODULE指定最終編譯出來的模塊名,如果是Android應用程序,通過LOCAL_PACKAGE_NAME變量來指定。

Ø指定目標模塊類型

模塊最終都要進行編譯,通過include 命令包含一些預定義好的變量來指定模塊最終的類型,這些變量分別對應一個makefile文件,包含了模塊類型的編譯過程。主要的預定義編譯變量如下:

編譯變量

功能

BUILD_SHARED_LIBRARY

將模塊編譯成共享庫

BUILD_STATIC_LIBRARY

將模塊編譯成靜態庫

BUILD_EXECUTABLE

將模塊編譯成可執行文件

BUILD_JAVA_LIBRARY

將模塊編譯成Java類庫

BUILD_PACKAGE

將模塊編譯成Android應用程序包

注:上述編譯變量的定義在build/core/definitions.mk中。

在Android.mk中,主要編譯變量如下表所示:

編譯變量

功能

LOCAL_PATH

指定編譯路徑

LOCAL_MODULE

指定編譯模塊名

LOCAL_SRC_FILES

指定編譯源碼列表

LOCAL_SHARED_LIBRARIES

指定使用的C/C++共享庫列表

LOCAL_STATIC_LIBRARIES

指定使用的C/C++靜態庫列表

LOCAL_STATIC_JAVA_LIBRARIES

指定使用的Java庫列表

LOCAL_CFLAGS

指定編譯器參數

LOCAL_C_INCLUDES

指定C/C++頭文件路徑

LOCAL_PACKAGE_NAME

指定Android應用程序名

LOCAL_CERTIFICATE

指定簽名認證

LOCAL_JAVA_LIBRARIES

指定使用的Java庫列表

LOCAL_SDK_VERSION

指定編譯Android應用程序時的SDK版本

注:其它的編譯變量見附錄。

4.1.3實驗:編譯HelloWorld應用程序

【實驗內容】

在Ubuntu系統中使用eclipse開發環境編寫簡單的HelloWorld應用程序,然后使用Android編譯系統進行編譯,最終將HelloWorld應用程序作為系統應用集成到Android系統中。

【實驗目的】

通過實驗,學員掌握在Android源碼的編譯系統中編譯Android應用程序、庫、可執行程序,了解Android系統應用程序的定制過程,最終在Android模擬器中,運行自己通過編譯系統編譯的Android應用程序。

【實驗平臺】

擁有Android源碼的Ubuntu操作系統(可以在Windows系統中虛擬Ubuntu系統)。

【實驗步驟】

1.打開eclipse開發環境,創建一個Android應用程序:HelloWorld:

$ cd ~/android/eclipse

$./eclipse &

2.將新創建的HelloWorld工程拷貝到源碼目錄中的packages/apps目錄下:

$ cp -rf HelloWorld/~/android/android_source/packages/apps

在HelloWorld工程目錄下刪除由eclipse開發環境自動生成的文件和目錄,僅保留如圖x-x所示工程目錄結構:

3.編譯HelloWorld工程的Android.mk文件,我們可以仿照Android里自帶的應用程序的Android.mk文件,例如Camera工程中的Android.mk文件:

將Camera工程中的Android.mk文件拷貝到HelloWorld工程中:

$ cp ../Camera/Android.mk./

修改Android.mk文件,刪除沒必要的編譯變量:

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE_TAGS := optional

LOCAL_SRC_FILES := $(call all-java-files-under,src)

LOCAL_PACKAGE_NAME :=HelloWorld

LOCAL_SDK_VERSION := current

include $(BUILD_PACKAGE)

4.編譯HelloWorld工程:

Ø切換到Android源碼目錄下:

$ cd ~/android/android_source/

Ø加載編譯函數:

$ source build/envsetup.sh

Ø選擇編譯目標項:

$ lunch generic-eng

Ø通過mmm命令編譯HelloWorld工程:

$ mmm packages/apps/HelloWorld/

Ø編譯生成模擬器映像system.img:

$ make snod

注:我們也可以直接通過make命令來編譯HelloWorld工程并生成system.img映像文件,但是這種方式耗時比較長,所以我們使用上面的編譯方式,能節省實驗時間,關于Android源碼編譯的細節,請查看2.3.2編譯Android章節。

5.啟動模擬器,查看HelloWorld應用程序運行效果:

$ ./run_emulator.sh

注:run_emulator.sh是快速運行模擬器的腳本,詳細說明請查看2.5定制Android模擬器章節。

總結

以上是生活随笔為你收集整理的深入浅出的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。