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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android Makefile分析

發布時間:2024/4/15 Android 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android Makefile分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

首先是可能用得到的基礎知識,必須了解基礎Makefile的語法,然后下面是Andriod用來編譯相應模塊使用的核心makefile,當然如果要速成的話也可以不看這些東西,直接按照后面的例子添加就可以了:
???? 1、prebuilt
????? /build/core/base_rules.mk
????? /build/core/prebuilt.mk
????? /build/core/multi_prebuilt.mk
???? 2、.so/
????? /build/core/base_rules.mk
????? /build/core/shared_library.mk
????? /build/core/dynamic_library.mk
????? /build/core/binary.mk
???? 3、.a
????? /build/core/base_rules.mk
????? /build/core/static_library.mk
????? /build/core/binary.mk
???? 編寫可執行文件基本上和.so是差不多的,現在分為兩類來仔細講一下,一類是prebuilt files的編譯,另外就是.so/.a/elf的編譯。
???? 在所有這許makefile中最重要的是base_rules.mk,它是對module進行處理的核心過程,下面先看看這個文件的內容:

??????

每個模塊在編譯的時候都會產生一個編譯目錄和一個安裝目錄,編譯目錄就是這個模塊編譯以后生成的目標文件,安裝目錄就代表著這個模塊是否會編譯進文件系統,就是是否編譯進IMG啦~~在base_rules.mk提供了兩個變量來定義你要輸出的目錄,仔細弄懂對你了解編譯后的生成目錄是很有幫助的~~
????? built_module_path := $(intermediates)
????? LOCAL_BUILT_MODULE := $(built_module_path)/$(LOCAL_BUILT_MODULE_STEM)
????? LOCAL_INSTALLED_MODULE := $(LOCAL_MODULE_PATH)/$(LOCAL_MODULE_SUBDIR)$(LOCAL_INSTALLED_MODULE_STEM)
????? built_module_path是編譯生成的中間文件所在的目錄,LOCAL_BUILT_MODULE_STEM就是你要生成的編譯目標啦,如果本地模塊指定了LOCAL_MODULE_STEM的話,它的值就是$(LOCAL_MODULE_STEM)$(LOCAL_MODULE_SUFFIX),如果沒有指定了的話就是$(LOCAL_MODULE)$(LOCAL_MODULE_SUFFIX)。由此可以看到LOCAL_MODULE的定義是很有講究的,比如什么*.so,一般*就用來作模塊名。LOCAL_MODULE_SUFFIX在編譯不同的模塊時,GOOGLE內置會給你加上相應的值,如果你不了解的話還是盡量自己來指定,不然可能編譯出來的東西被篡改了文件名哦噢~~
????? 將編譯目錄的文件拷貝到安裝目錄就是我們的LOCAL_INSTALLED_MODULE了,是否會安裝就要看你定義的 LOCAL_MODULE_TAGS了,當然你也可以通過修改LOCAL_MODULE_PATH來自定義安裝。LOCAL_MODULE_PATH是有個很有用的變量,首先我們看看當我們在本地模塊沒有指定這個值的時候,它的值實際上是:LOCAL_MODULE_PATH := $($(my_prefix)OUT$(use_data)_$(LOCAL_MODULE_CLASS)),如果你的模塊定義了TAGS := TESTS則user_data的值是DATA,這樣的模塊會被安裝在data/目錄下,那么通過替換我們就知道這個LOCAL_MODULE_PATH := TARGET_OUT_$(LOCAL_MODULE_CLASS)。這個LOCAL_MODULE_CLASS在特定的類型編譯會被google賦值成固定內容,但是在prebuilt的編譯中它是由你自己來賦值的,它的值就會用來定義生成的目錄,比如LOCAL_MODULE_CLASS := ETC的時候,則就會被安裝在/system/etc目錄。那么我們就知道如何來定義prebuilt模塊里面的CLASS了,google還提供了一個 LOCAL_MODULE_SUBDIR可以讓你來定義子目錄,但是要記得的是在每個模塊的最后要將這個值清空,因為默認CLEAR_VARS是不會清空這個值的。
????? 當然前面說的是LOCAL_MODULE_PATH的默認值,我們可以通過給它賦值來強制指定安裝的目錄,比如說要安裝在system/etc /permissions目錄,則可以強制指定它的值為$(TARGET_OUT_ETC)/permissions,這樣模塊就會被強制安裝在這個目錄了,給LOCAL_MODULE_PATH賦值的情況主要應用在prebuilt模塊的編譯上,其他的應該盡量采用其默認值。
????? 下面我們就具體看看我寫的一個如何編譯自己的.so *.a elf的例子,具體能使用到的變量,和要注意的地方我都寫出來了:

?????????

這里要說明的是這個prelink,prelinke只有在編譯.so的時候才會有的選項,主要是通過預鏈接的方式來加快程序啟動和執行的速度,如果你的本地模塊prelink是真的話,那你要在build/core/prelink-linux-arm.map中定義你的庫需要使用的空間,空間不夠的話會報錯(具體使用沒仔細研究過)
?????? 下面再看看如何來將我們自己的prebuilt files編譯進工程,先讓我們和這個相關的最重要的兩個makefile:

????????

multi_prebuilt.mk只用來加入需要加入的各種庫,仔細注意它里面的那個對加入文件進行處理的函數,尤其是 LOCAL_MODULE,LOCAL_MODULE_SUFFIX ,LOCAL_SRC_FILES這3個變量是如何得到的,使用multi_prebuilt編譯進工程的文件都會自動打上USER的tag。而且它最后還是會掉用prebuilt.mk來執行真正的編譯操作。
??????? prebuilt.mk實際上可以編譯任何文件到我們的工程中,下面是我寫的一個例子,可以自動將目錄下相應格式的文件編譯進工程:

??????

此外添加prebuilt.mk也有一個粗暴的方式,可以通過下面的規則簡單的將所有prebuilt files添加到你工程中去,必須一個一個添加:
??????? LOCAL_PATH := $(call my-dir)
??????? include $(CLEAR_VARS)
??????? # your prebuilt file name
??????? LOCAL_MODULE := example.so
??????? LOCAL_MODULE_TAGS := user eng
??????? # your prebuilt file (must be relative directory )
??????? LOCAL_SRC_FILES := lib/example.so
??????? # the path your prebuilt file will be installed?? $(TARGET_OUT) is the system directory
??????? LOCAL_MODULE_PATH := $(TARGET_OUT)/lib??
??????? include (BUILD_PREBUILT)

在最后說一下Android對模塊唯一性檢測的規則,在base_rules.mk里面通過module_id里來檢測這個模塊是否已經存在,我們看看這個值是如何定義的:

module_id := MODULE.$(if /
??? $(LOCAL_IS_HOST_MODULE),HOST,TARGET).$(LOCAL_MODULE_CLASS).$(LOCAL_MODULE)

所以它是通過LOCAL_MODULE_CLASS和LOCAL_MODULE這兩個變量來檢測模塊的唯一性,因此當你定義同一樣的CLASS和 MODULE的時候,Android就會報錯,提示模塊必須是唯一的。因此如果你將LOCAL_MODULE_CALSS進行修改,使用 LOCAL_MODULE_PATH來指定安裝目錄的時候就會逃過Android對模塊唯一性的檢測,但是這樣導致的問題就是同一個目標會有多個規則來實現它,而且每個規則都是相同的命令。這樣導致的結果就是MAKE會將所有的依賴放在一起,然后使用命令來將其生成目標,這樣是非常危險的,會造成庫的覆蓋,而且很多時候你不知道它就究竟使用的是哪個依賴來最終生成目標,只能用md5sum來檢查。

????? 因此當你使用prebuilt來覆蓋系統原有的文件的時候應該特別小心,如果你確認你的文件在覆蓋系統原有文件以后系統能正常運行的話,好的方法是還是打開Android對module_id的檢測,同時把原來生成這個文件的Makefile進行修改,讓其不編譯出這個文件~

????? 最后補充一個Android如何來存放模塊的編譯中間文件:
1、如果你的LOCAL_MODULE_CLASS包含COMMON_MODULE_CLASS := JAVA_LIBRARIES NOTICE_FILES,則你編譯出的中間文件會放在:
?? $(TARGET__OUT_COMMON_INTERMEDIATES)/$(LOCAL_MODULE_CLASS)/$(LOCAL_MODULE)_intermediates/
TARGET_OUT_COMMON_INTERMEDIATES := out/target/common/obj
2、如果你的LOCAL_MODULE_CLASS不包含COMMON_MODULE_CLASS,則你編譯出的中間文件會放在:
???? $(TARGET__OUT_INTERMEDIATES)/$(LOCAL_MODULE_CLASS)/$(LOCAL_MODULE)_intermediates/
TARGET_OUT_INTERMEDIATES := out/target/product/msm7627_ffa/ob

總結

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

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