色yeye在线视频观看_亚洲人亚洲精品成人网站_一级毛片免费播放_91精品一区二区中文字幕_一区二区三区日本视频_成人性生交大免费看

當前位置:首頁 > 嵌入式培訓 > 嵌入式學習 > 講師博文 > Android.mk分析

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

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

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

一、簡單的Android.mk

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

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

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

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

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

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

函數具體是如何實現的?

我們重點關注紅顏標注的地方,MAKEFILE_LIST是make解釋器內部定義的變量,它的含義就是獲取它所尋找 到的Makefile文件的絕對路徑列表。當我們在源碼目錄的頂層目錄進行"mmm"進行編譯的時候,Android的編 譯系統就會使用make工具找到相關的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

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

(2) include $(CLEAR_VARS)

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

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

(3)LOCAL_MODULE

用來指定當前模塊的名稱

(4)LOCAL_SRC_FILES

用來指定當前模塊需要參與編譯的文件

(5)include $(BUILD_EXECUTABLE)

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

executable.mk文件中定義了如何編譯設備上的可執行文件。

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

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

可以參與編譯。

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

我們的Android.mk的內容如下:

LOCAL_MODULE_PATH = $(LOCAL_PATH)/bin

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

(2)調用Android編譯系統的函數,獲取當前模塊下所有需要編譯的文件

我們以獲取C語言為例,來看看函數的具體實現:

(1)all-c-files-under

(2)all-subdir-c-files

嗯,對比一下兩者的區別:

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

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

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

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

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

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

三、編譯靜態庫和動態庫

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

(1)BUILD_SHARED_LIBRARY

將模塊編譯成動態庫 , 例如:libadd_sub.so

(2)BUILD_STATIC_LIBRARY

將模塊編譯成靜態庫 , 例如:libadd_sub.a

四、鏈接庫

1、鏈接Android系統中自帶的庫

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

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

(1)LOCAL_SHARED_LIBRARIES

告訴編譯系統需要鏈接的Android系統提供的動態庫

(2)LOCAL_STATIC_LIBRARIES

告訴編譯系統需要鏈接的Android系統提供的靜態庫

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

LOCAL_LDFLAGS

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

五、預置編譯

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

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

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

編譯效果如下:

解釋如下:

(1)LOCAL_MODULE

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

(2)LOCAL_SRC_FILES

需要預置到系統中的文件

(3)LOCAL_MODULE_TAGS

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

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

(4)LOCAL_MODULE_CLASS

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

APPS apk文件

SHARED_LIBRARIES 動態庫文件

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

ETC 其他格式文件

(5)BUILD_PREBUILT 和 BUILD_MULTI_PREBUILT

不同點:

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

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

BUILD_MULTI_PREBUILT只能將文件拷貝到Android系統指定的路徑下。

六、引入第三方jar包

很多時候我們在做APP開發的時候都會用到第三方的jar包,那如何在Android系統中引入第三方jar包,編譯

java代碼生成apk文件呢?

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

Calculator app應用程序使用到了第三方的arity-2.1.2.jar文件,而arity-2.1.2.jar文件在Calculator當前目錄下,為了 方便引用arity-2.1.2.jar文件這里先通過預置編譯將arity-2.1.2.jar拷貝到Android 系統的相應目錄下,這樣開始 編譯Calculator應用程序的時候才可以找到它依賴的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

指定當前模塊依賴的jar包

(2)LOCAL_SDK_VERSION

指定當前SDK的版本為Android源碼中的SDK版本

(3)LOCAL_PACKAGE_NAME

指定生成的apk文件的名字

(4)LOCAL_CERTIFICATE

指定apk文件的簽名。可以指定的值有:testkey、media、platform、shared這四種,可以在源碼 build/target/product/security里面看到對應的秘鑰,其中shared.pk8代表私鑰,shared.x509.perm代表公鑰,一定 是成對出現的。

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

(5)BUILD_PACKAGE

將模塊編譯成APK文件

(6)LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES

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

上一篇:Android init進程之如何進入java世界

下一篇:moc文件分析

熱點文章推薦
華清學員就業榜單
高薪學員經驗分享
熱點新聞推薦
前臺專線:010-82525158 企業培訓洽談專線:010-82525379 院校合作洽談專線:010-82525379 Copyright © 2004-2022 北京華清遠見科技集團有限公司 版權所有 ,京ICP備16055225號-5,京公海網安備11010802025203號

回到頂部

主站蜘蛛池模板: 亚洲AV无码专区亚洲AV网站 | 久久精品黄AA片一区二区三区 | 亚洲精品久久无码 | 国产人妻人伦精品一区二区网站 | 麻豆视传媒在线观看 | gogogo欧洲免费视频 | 欧美性xxxx禁忌 | 好吊色欧美一区二区三区四区 | 8x8×拨牐拨牐永久免费视频 | 黄色天堂在线观看 | 欧美另类videossexo高潮 | 香港经典A毛片免费观看播放 | 爆乳一丝丝不挂裸体大胸美女 | 极品JK小仙女呻吟自慰 | 嫩菊在线观看免费视频 | 国内精品久久久久影院优 | 青春草av | 亚洲av日韩av永久无码久久 | 在线观看中文视频 | 国产迷姦播放在线观看 | 国产中文成人精品久久久 | 久久AV无码精品人妻系列 | 日韩一区二区视频在线 | 色综合久久99 | 两个人在线观看WWW视频 | 国产裸拍裸体视频在线观看 | 精品中文字幕在线播放 | 性欧美激情aa在线看 | 偷窥国产亚洲女爱视频在线 | 无码人妻aⅴ一区二区三区鲁大师 | 欧美狂野乱码一二三四区 | 国产会所在线观看 | 中国av大片 | 日产特黄极日产 | 亚洲Aⅴ天堂Av天堂无码麻豆 | 激情亚洲一区国产精品 | 三级网站久久 | 亚洲AV无码国产精品色午夜软件 | 亚洲国产精品成人网址天堂 | 久久精品国产69国产精品亚洲 | 国产偷窥熟妇高潮呻吟 |