国产成人精品三级麻豆,色综合天天综合高清网,亚洲精品夜夜夜,国产成人综合在线女婷五月99播放,色婷婷色综合激情国产日韩

當(dāng)前位置:首頁 > 嵌入式培訓(xùn) > 嵌入式學(xué)習(xí) > 講師博文 > Android.mk分析

Android.mk分析 時間:2018-09-26      來源:未知

在Android的源碼中每個目錄下幾乎都有一個Android.mk的文件,這個文件就是用來管理當(dāng)前目錄或子目錄 下的文件進(jìn)行編譯的。我們打開 Android.mk文件,我們會發(fā)現(xiàn)它并沒有太多的Makefile語法,更多的是一些大寫的宏,例 如:LOCAL_PATH,LOCAL_MODULE等。此時我們就會在想,"Android源碼下的文件是如何編譯的呢?",實(shí)際上 Android源碼已經(jīng)有比較完善的編譯系統(tǒng),它是以模塊化的思想設(shè)計(jì)編譯系統(tǒng)的,Android源碼的每個目錄幾 乎都可以當(dāng)獨(dú)編譯,我們可以給予這個編譯系統(tǒng),編寫自己的Android.mk文件,將我們需要的文件進(jìn)行編 譯。

Android的編譯系統(tǒng)相關(guān)的文件存放在Android源碼目錄下的build/core目錄下,這里不介紹Android源碼的 編譯系統(tǒng),如果想了解Android編譯系統(tǒng)的讀者可以自己在網(wǎng)上查閱相關(guān)的資料。好了下面我們就來看看如何 編寫自己的Android.mk吧!

一、簡單的Android.mk

從編譯一個史上第一個程序開始吧,編寫編譯hello.c的Android.mk。

hello.c文件中的內(nèi)容我想你是會寫的,這里就不貼出來了,下面我們來編譯一下這個模塊。

設(shè)置好了編譯環(huán)境,下面我們就來編譯我們的模塊吧!我的模塊放在Android源碼目錄下的external/test/test1目 錄下。

嗯,我們很輕松的就完成了在Android源碼目錄下編譯自己的模塊,下面我們來詳細(xì)分析一下每個變量的具體 含義。

(1) LOCAL_PATH := $(call my-dir)

$(call my-dir)這種寫法是Makefile中調(diào)用一個自定義函數(shù)的寫法,也就是獲取my-dir這個自定義函數(shù)的結(jié)果。下 面我們來看看my-dir這個

函數(shù)具體是如何實(shí)現(xiàn)的?

我們重點(diǎn)關(guān)注紅顏標(biāo)注的地方,MAKEFILE_LIST是make解釋器內(nèi)部定義的變量,它的含義就是獲取它所尋找 到的Makefile文件的絕對路徑列表。當(dāng)我們在源碼目錄的頂層目錄進(jìn)行"mmm"進(jìn)行編譯的時候,Android的編 譯系統(tǒng)就會使用make工具找到相關(guān)的Makefile文件。我們的模塊里面的Makefile就是后一個Makefile文件 了。

LOCAL_MODULE_MAKEFILE := $$(lastword $$(MAKEFILE_LIST)) 獲取后一個Makefile文件絕對 路徑

$(dir $(LOCAL_MODULE_MAKEFILE)) 獲取目錄路徑,不包含文件 例如:$(dir /home/linux/Makefile) ->

/home/linux/

$(patsubst %/, %, /home/linux/) -> /home/linux

好了,我們總結(jié)一下 $(call my-dr)的終極含義:獲取當(dāng)前模塊的路徑

(2) include $(CLEAR_VARS)

CLEAR_VARS這個變量在Android源碼樹下的build/core/config.mk文件中定義:

include類似于C語言中的頭文件包含,嗯,它的含義就是在我們的Android.mk文件中包含編譯系統(tǒng)目錄下的 clear_vars.mk這個文件中的內(nèi)容。clear_vars.mk中就是將一些編譯的時候需要用到的一些變量清空。但是我可 以肯定它一定不會把LOCAL_PATH這個變量清空,想想為什么?

(3)LOCAL_MODULE

用來指定當(dāng)前模塊的名稱

(4)LOCAL_SRC_FILES

用來指定當(dāng)前模塊需要參與編譯的文件

(5)include $(BUILD_EXECUTABLE)

BUILD_EXECUTABLE這個變量在Android源碼樹下的build/core/config.mk文件中定義:

executable.mk文件中定義了如何編譯設(shè)備上的可執(zhí)行文件。

二、編譯模塊下的多個文件

上面的Android.mk中我們只編譯了一個文件,如果有多個文件需要編譯該如何做呢?在Android的編譯系統(tǒng) 中,我們有兩種方法讓多個文件

可以參與編譯。

(1)將需要編譯的文件名都指定在LOCAL_SRC_FILES變量 例如:在我們的test1目錄下還有兩個文件 add.c 和 sub.c ,這兩個文件中的內(nèi)容如下:

我們的Android.mk的內(nèi)容如下:

LOCAL_MODULE_PATH = $(LOCAL_PATH)/bin

表示將編譯好的模塊存放在模塊所在目錄的bin子目錄下

(2)調(diào)用Android編譯系統(tǒng)的函數(shù),獲取當(dāng)前模塊下所有需要編譯的文件

我們以獲取C語言為例,來看看函數(shù)的具體實(shí)現(xiàn):

(1)all-c-files-under

(2)all-subdir-c-files

嗯,對比一下兩者的區(qū)別:

(1)all-c-files-under 比較靈活,可以指定模塊下一個指定的子目錄下搜索所有的c語言文件 (2)all-subdir-c-files 是獲取模塊下所有的子目錄下的C語言文件 注意:在這里函數(shù)中,尋找Makefile文件的時候只會遞歸一級子目錄

好了,我們來看看我們修改后的Android.mk文件吧!

我們把所有的C語言文件存放在了src子目錄下,所以這里指定的是在src子目錄下搜索。

我們在hello.c中調(diào)用了add和sub函數(shù),沒有聲明,所以編譯的時候報(bào)了警告,下面我們自己定義一個hello.h的頭

文件,在這個頭文件中 我們聲明這兩個函數(shù)。

問題:如何在Android.mk文件中指定自己的頭文件搜索路徑?

三、編譯靜態(tài)庫和動態(tài)庫

前面我們通過Android.mk將我們模塊中的代碼編譯成了ELF格式的可執(zhí)行文件,下面我們來看看如何將自己的 模塊編譯成庫。

(1)BUILD_SHARED_LIBRARY

將模塊編譯成動態(tài)庫 , 例如:libadd_sub.so

(2)BUILD_STATIC_LIBRARY

將模塊編譯成靜態(tài)庫 , 例如:libadd_sub.a

四、鏈接庫

1、鏈接Android系統(tǒng)中自帶的庫

ALOGE是Android系統(tǒng)中用來輸出log信息的函數(shù),它在liblog.so中,所以我們在編譯我們的代碼時候,要告訴 編譯系統(tǒng),需要去連接liblog.so這個動態(tài)庫。

我們的Android.mk寫成如下形式:

(1)LOCAL_SHARED_LIBRARIES

告訴編譯系統(tǒng)需要鏈接的Android系統(tǒng)提供的動態(tài)庫

(2)LOCAL_STATIC_LIBRARIES

告訴編譯系統(tǒng)需要鏈接的Android系統(tǒng)提供的靜態(tài)庫

2、鏈接第三方庫 我們將add.c和sub.c編譯成libadd_sub.so,然后我們在test.c中調(diào)用add和sub這兩個函數(shù),此時Android.mk應(yīng)該寫 成如下形式:

LOCAL_LDFLAGS

指定鏈接參數(shù), -L 指定需要連接的庫所在的路徑, -l指定庫的名字

五、預(yù)置編譯

所謂的預(yù)置編譯指的是將一個編譯好的可執(zhí)行文件或APK以及他們依賴的庫、jar包拷貝到Android系統(tǒng)源 碼相關(guān)的存放路徑下,這樣我們在對Android 系統(tǒng)就行打包生成system.img鏡像時,這些東西就會被打包進(jìn) 去。哦,還有就是當(dāng)我們引入第三方庫或

問:為了不自己手動把這些東西拷貝到Android源碼對應(yīng)的目錄下,然后在打包呀? 答:麻煩,Android版本總是在升級,目錄結(jié)構(gòu)也總是在發(fā)生變化,使用預(yù)置編譯,所以的事情都由Android系 統(tǒng)自帶的編譯系統(tǒng)去做,這樣就何樂而不為呢?

下面我們以預(yù)置libadd_sub.so文件到Android系統(tǒng)中為例,來講解預(yù)置編譯的使用方法:

編譯效果如下:

解釋如下:

(1)LOCAL_MODULE

這里的含義和以前的含義不一樣,它表示文件(xx.apk/jar/so)預(yù)置到系統(tǒng)中之后的名字。例如:libadd_sub.so預(yù) 置之后的名字為libaddsub.so

(2)LOCAL_SRC_FILES

需要預(yù)置到系統(tǒng)中的文件

(3)LOCAL_MODULE_TAGS

這個變量可以賦值為user 、eng、tests、optional

user 指該模塊只在user版本下才編譯 eng 指該模塊只在eng版本下才編譯 tests 指該模塊只在tests版本下才編譯 optional 指該模塊在所有版本下都編譯

(4)LOCAL_MODULE_CLASS

這個變量用來指定文件類型,它可以賦的值有

APPS apk文件

SHARED_LIBRARIES 動態(tài)庫文件

JAVA_LIBRARIES dex歸檔文件 EXECUTABLES ELF格式文件

ETC 其他格式文件

(5)BUILD_PREBUILT 和 BUILD_MULTI_PREBUILT

不同點(diǎn):

<1>BUILD_PREBUILT 只能針對一個文件, BUILD_MUTI_PREBUILT針對多個文件

<2>BUILD_PREBUILT 在預(yù)置的時候可以通過LOCAL_MODULE_PATH將文件拷貝到自己指定的路徑下,而

BUILD_MULTI_PREBUILT只能將文件拷貝到Android系統(tǒng)指定的路徑下。

六、引入第三方j(luò)ar包

很多時候我們在做APP開發(fā)的時候都會用到第三方的jar包,那如何在Android系統(tǒng)中引入第三方j(luò)ar包,編譯

java代碼生成apk文件呢?

我們來看看Android源碼中packages/apps/Calculator目錄下Android.mk的寫法。

Calculator app應(yīng)用程序使用到了第三方的arity-2.1.2.jar文件,而arity-2.1.2.jar文件在Calculator當(dāng)前目錄下,為了 方便引用arity-2.1.2.jar文件這里先通過預(yù)置編譯將arity-2.1.2.jar拷貝到Android 系統(tǒng)的相應(yīng)目錄下,這樣開始 編譯Calculator應(yīng)用程序的時候才可以找到它依賴的jar包。

我們看看它的編譯流程:

make: Entering directory `/home/a/workdir/androidL'

target R.java/Manifest.java: Calculator (out/target/common/obj/APPS/Calculator_intermediates/src/R.stamp) target Prebuilt: Calculator (out/target/common/obj/JAVA_LIBRARIES/libarity_intermediates/classes.jar) target Prebuilt: Calculator (out/target/common/obj/JAVA_LIBRARIES/libarity_intermediates/javalib.jar) target Java: Calculator (out/target/common/obj/APPS/Calculator_intermediates/classes)

Copying: out/target/common/obj/APPS/Calculator_intermediates/classes-jarjar.jar

Copying: out/target/common/obj/APPS/Calculator_intermediates/emma_out/lib/classes-jarjar.jar Copying: out/target/common/obj/APPS/Calculator_intermediates/classes.jar

Proguard: out/target/common/obj/APPS/Calculator_intermediates/proguard.classes.jar ProGuard, version 4.10

Reading program jar [/home/a/workdir/androidL/out/target/common/obj/APPS/Calculator_intermediates/classes.jar] Reading library jar [/home/a/workdir/androidL/out/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates/classes.ja r]

Preparing output jar [/home/a/workdir/androidL/out/target/common/obj/APPS/Calculator_intermediates/proguard.classes.jar] Copying resources from program jar [/home/a/workdir/androidL/out/target/common/obj/APPS/Calculator_intermediates/classes.jar]

target Dex: Calculator

Copying: out/target/common/obj/APPS/Calculator_intermediates/classes.dex

target Package: Calculator (out/target/product/fspad-733/obj/APPS/Calculator_intermediates/package.apk) Notice file: packages/apps/Calculator/NOTICE -- out/target/product/fspad- 733/obj/NOTICE_FILES/src//system/app/Calculator/Calculator.apk.txt

Install: out/target/product/fspad-733/system/app/Calculator/Calculator.apk target Prebuilt: libarity (out/target/product/fspad- 733/obj/JAVA_LIBRARIES/libarity_intermediates/javalib.jar)

make: Leaving directory `/home/a/workdir/androidL'

好了,下面我們來看看這個Android.mk中我們前面沒有用過的變量。

(1)LOCAL_STATIC_JAVA_LIBRARIES

指定當(dāng)前模塊依賴的jar包

(2)LOCAL_SDK_VERSION

指定當(dāng)前SDK的版本為Android源碼中的SDK版本

(3)LOCAL_PACKAGE_NAME

指定生成的apk文件的名字

(4)LOCAL_CERTIFICATE

指定apk文件的簽名?梢灾付ǖ闹涤:testkey、media、platform、shared這四種,可以在源碼 build/target/product/security里面看到對應(yīng)的秘鑰,其中shared.pk8代表私鑰,shared.x509.perm代表公鑰,一定 是成對出現(xiàn)的。

其中testkey是作為android編譯的時候默認(rèn)的簽名key,如果系統(tǒng)中的apk的Android.mk中沒有設(shè)置 LOCAL_CERTIFICATE的值,就默認(rèn)使用testkey。而如果設(shè)置成LOCAL_CERTIFICATE :=platform就代表使用 platform來簽名,這樣的話這個apk就擁有了和system相同的簽名,因?yàn)橄到y(tǒng)級別的簽名也是使用platform來簽 名的。

(5)BUILD_PACKAGE

將模塊編譯成APK文件

(6)LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES

指定prebuilt jar庫的規(guī)則,格式 別名 : jar文件路徑。注意:別名一定要與 LOCAL_STATIC_JAVA_LIBRARIES里所取的別名一致,且不含jar;jar文件路徑一定要是真實(shí)的存放第 三方j(luò)ar包的路徑。編譯用BUILD_MULTI_PREBUILT。

上一篇:Android init進(jìn)程之如何進(jìn)入java世界

下一篇:moc文件分析

熱點(diǎn)文章推薦
華清學(xué)員就業(yè)榜單
高薪學(xué)員經(jīng)驗(yàn)分享
熱點(diǎn)新聞推薦
前臺專線:010-82525158 企業(yè)培訓(xùn)洽談專線:010-82525379 院校合作洽談專線:010-82525379 Copyright © 2004-2022 北京華清遠(yuǎn)見科技集團(tuán)有限公司 版權(quán)所有 ,京ICP備16055225號-5,京公海網(wǎng)安備11010802025203號

回到頂部