. 常見AOSP目錄
目錄名 | 介紹 |
---|---|
build/core/Makefile | AOSP整個編譯過程中核心的編譯規則makefile |
build/envsetup.sh | 編譯初始化腳本 |
build/target | AOSP自帶的Target(模擬器)的一些makefile |
build/tools/ | 編譯中使用的shell及python寫的工具腳本 |
packagess | 系統app以及一些provider,輸入法等桌面看不到的app |
framework/av/ | 多媒體相關的native層源碼目錄 |
framework/webview/ | 瀏覽器內核chromium的源碼目錄 |
framework/native/ | power、surface、input、binder等服務的native層實現源碼目錄 |
framework/base/core/ | framework.jar、framework-res.apk、libandroid_runtime.so等的源文件 |
framework/base/native/ | libandroid.so的源代碼目錄.java中的api的native實現.比如looper,assertManager |
framework/base/media/ | 多媒體相關的JavaApi和jni層的源文件 |
framework/base/packages/ | SettingProviders,SystemUI等不在桌面啓動的APP源碼 |
framework/base/service/ | service.jar、libandroid_service.so的源文件,wifi服務相關的JavaApi,WifiManager,WifiService等 |
device/(vendor_name)/(product_name) | 跟某些廠商的某個硬件平臺相關的內核,硬件配置等 |
vendor/(vendor_name)/(product_name) | 廠商對AOSP進行的修改或者定製,放在vendor目錄。包括但不限於framework層新增API,新增APP等業務需求,但是現在Google更推薦放在devices目錄下 |
/out/host | 該目錄下包含了針對當前操作系統所編譯出的Android開發工具產物,例如adb,aapt,fastboot等命令 |
/out/target/common/ | 該目錄包含了針對Android設備的通用的編譯產物,主要是java應用代碼和java庫。Framework.jar,services.jar,android.policy.jar等等 |
/out/target/(product)/(product_name) | 包含了針對特定設備的編譯結果以及平臺相關的C/C++庫和二進制文件。其中,product_name是具體目標設備的名稱 |
2. AndroidBuildSystem
andorid build系統用來編譯android系統,android sdk以及相關文檔.該系統主要由make文件,shell腳本以及python腳本組成,在編譯時能夠支持面向不同的硬件設備,不同的編譯類型,且提供面向各個廠商的定製擴展。
2.1 什麼是makefile
makefile是一些有特定語法的,可供make命令讀取並執行的腳本性質的配置文件。作用就是可以告知編譯系統,對哪些源文件進行編譯,怎麼編譯,怎麼處理依賴關係。makefile可以定義變量,函數,調用系統命令,shell、python腳本,管理module之間的依賴。整個Android Build系統中的 Make 文件可以分爲三類:
- Build系統核心 Makefile
這類makefile定義了整個Build系統的框架,而其他所有Make文件都是在這個框架的基礎上編寫出來的。位於/build/core目錄下。 - 針對某個產品的Makefile
這類makefile是針對某個產品Make文件,這些文件通常位於device/<vendor>/<product>目錄下。 - 針對某個模塊的Makefile
Android.mk
第三類是針對某個模塊的makefile文件.AOSP中,不會針對某一個文件進行編譯,每一個編譯單位都是一個模塊,每一個模塊由一個名爲"Android.mk
"的makefile來聲明。該文件中定義瞭如何編譯當前模塊。
2.2 make文件中的內容
LOCAL_PATH := $(call my-dir)
表示源代碼的目錄在哪include $(CLEAR_VARS)
表示變量全部清空,其中CLEAR_VARS也是一個makefile文件LOCAL_MODULE_TAGS := optional
表示是哪個TAG,可爲eng,user,userdebug,optional等,在哪個版本下執行編譯等...
3. ABS思維導圖
ABS思維導圖
ps:原諒我不會在markdown上畫思維導圖
android編譯.png
略醜的流程圖
ps:圖不是重點,重點是掌握build系統的流程
ABS流程.jpg
附上文字描述:
第一步: 在項目根目錄執行 make 命令即就找到當前目錄的makefile文件,文件什麼也沒有就引用build/core/main.mk文件:
### DO NOT EDIT THIS FILE ###
include build/core/main.mk
### DO NOT EDIT THIS FILE ###
build/core/main.mk
:- 檢查當前的編譯環境inclue build/core/下的核心makefile文件從而完成編譯環境的配置
- 檢索所有的
BoardConfig.mk
和AndroidProduct.mk
載入到編譯系統 main.mk
裏會使用python腳本遍歷AOSP下的所有模塊(AndroidProduct.mk
)並include
所有模塊下的AndroidProduct.mk
:
告訴編譯系統,當前module的一些配置信息(源文件,依賴庫等)和編譯輸出類型(可執行文件,共享庫,靜態庫,java庫,app等)。根據不同的輸出類型,會include不同的makefile(package.mk java_library.mk等
),這些makefile會調用相關的編譯工具,達到編譯目的
作者:RexHuang
鏈接:https://www.jianshu.com/p/d6e752636ba3
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯繫作者獲得授權並註明出處。
#必備的兩行,聲明LOCAL_PATH變量,也就是當前的路徑
#並清除其它變量
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
#包名,這生成的apk名字。這裏的話會生成Hello.apk
LOCAL_PACKAGE_NAME := Hello
LOCAL_CERTIFICATE := platform
#如果使用的系統的包,需要引入他們使用的資源文件,否則會提示編譯資源找不到的錯誤
LOCAL_RESOURCE_DIR += $(LOCAL_PATH)/res
LOCAL_RESOURCE_DIR += frameworks/support/v7/appcompat/res
#LOCAL_RESOURCE_DIR += frameworks/support/v7/gridlayout/res
#LOCAL_RESOURCE_DIR += frameworks/support/v7/recyclerview/res
#指定該模塊的編譯版本爲optional
#user: 指該模塊只在user版本下才編譯
#eng: 指該模塊只在eng版本下才編譯
#tests: 指該模塊只在tests版本下才編譯
#optional:指該模塊在所有版本下都編譯
LOCAL_MODULE_TAGS := tests
#源碼所在目錄,這裏就在當前位置的java目錄下。所以直接寫java
LOCAL_SRC_FILES := $(call all-java-files-under, java)
#LOCAL_SRC_FILES += \
# src/xx/xx/xx/XxxOne.aidl \
# src/xx/xx/xx/XxxTwo.aidl
#依賴的jar包,包括系統的和第三方的(放在libs目錄)jar包
LOCAL_STATIC_JAVA_LIBRARIES += android-support-v4 \
android-support-v7-appcompat
#android-support-v7-recyclerview
原文有詳細說明關於混淆:https://blog.csdn.net/wolfboy2/article/details/51673429
#混淆文件名
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
#關閉混淆
LOCAL_PROGUARD_ENABLED := disabled
在需要混淆的工程目錄下(package/apps/下的工程)添加proguard.flags文件,該文件即爲網絡傳說中的proguard.cfg,只是命名不一樣而已,然後再Android.mk中添加如下兩句:
LOCAL_PROGUARD_ENABLED := full
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
上面的full 也可以是custom,如果不寫這句,那還得添加如下一句:
TARGET_BUILD_VARIANT := user或者TARGET_BUILD_VARIANT := userdebug
這樣後在工程目錄下執行mm便可以看到在out目錄下生成了形如proguard.classes.jar的東東,這就說明已在編譯中啓動了proguard
但反編譯一看,並未出現網絡雲說的abcd替代符號,其實代碼並未真正混淆:
android在編譯時默認關閉了混淆選項,有去研究build/core目錄的同志會發現這裏也有個proguard.flags文件,其實在proguard的過程中,編譯器會調用包括本地目錄下和系統定義了的多個proguard.flags文件,而在這個文件中混淆的選項被禁止了,故而編譯出來的apk仍未混淆。因此將如下句子註釋掉便可實現真正的混淆編譯:
# Don't obfuscate. We only need dead code striping.
-dontobfuscate(將該句加個#號註釋掉)
LOCAL_AAPT_FLAGS := --auto-add-overlay
LOCAL_AAPT_FLAGS += --extra-packages android.support.v7.appcompat
#LOCAL_AAPT_FLAGS += --extra-packages android.support.v7.gridlayout
#LOCAL_AAPT_FLAGS += --extra-packages com.android.datetimepicker
#LOCAL_AAPT_FLAGS += --extra-packages android.support.v7.recyclerview
#打包成apk
include $(BUILD_PACKAGE)
include $(call all-makefiles-under,$(LOCAL_PATH))
如何將一個應用編譯時生成到pri-app中呢?需要在Android.mk中做如下設置即可:
LOCAL_PRIVILEGED_MODULE := true
1、帶源碼的apk
1)&nBSP; 在 packages/apps 下面以需要預置的 APK的 名字創建一個新文件夾,以預置一個名爲Test的APK 爲例
2) 將 Test APK的Source code 拷貝到 Test 文件夾下,刪除 /bin 和 /gen 目錄
3) 在 Test 目錄下創建一個名爲 android.mk的文件,內容如下:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-subdir-Java-files)
LOCAL_PACKAGE_NAME := Test
include $(BUILD_PACKAGE)
4) 打開文件 build/target/product/${Project}.mk (其中 ${Project} 表示工程名)或者是在build/target/product/core.mk文件 或者是 device/mediatek/productname/device.mk,因各自公司而易
將 Test 添加到 PRODUCT_PACKAGES 裏面。
5) 重新 build 整個工程
2、無源碼的apk
1) 在 packages/apps 下面以需要預置的 APK 名字創建文件夾,以預置一個名爲Test的APK爲例
2) 將 Test.apk 放到 packages/apps/Test 下面
3) 在 packages/apps/Test 下面創建文件 Android.mk,文件內容如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Module name should match apk name to be installed
LOCAL_MODULE := Test
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_CERTIFICATE := PRESIGNED
include $(BUILD_PREBUILT)
4) 打開文件 build/target/product/${Project}.mk (其中 ${Project} 表示工程名)或者是在build/target/product/core.mk文件 或者是 device/mediatek/productname/device.mk,因各自公司而易
將 Test 添加到 PRODUCT_PACKAGES 裏面。
5) 將從Test.apk解壓出來的 so庫拷貝到alps/vendor/mediatek/${Project}/artifacts/out/target/product/${Project}/system/lib/目錄下,若無 so 庫,則去掉此步;
6) 重新 build 整個工程
注:Google在KK上修改protection Level爲System的permission控管機制
如果App使用System Level的permission,需要預置到/system/priv-app底下 (原在/system/app)。
3、app可以卸載但是恢復出廠設置時不能恢復
1) 在 packages/apps 下面以需要預置的 APK 名字創建文件夾,以預置一個名爲Test的APK爲例
2) 將 Test.apk 放到 packages/apps/Test 下面;
3) 在 packages/apps/Test 下面創建文件 Android.mk,文件內容如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Module name should match apk name to be installed
LOCAL_MODULE := Test
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_CERTIFICATE := PRESIGNED
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
include $(BUILD_PREBUILT)
4) 打開文件 build/target/product/${Project}.mk (其中 ${Project} 表示工程名)或者是在build/target/product/core.mk文件 或者是 device/mediatek/productname/device.mk,因各自公司而易
將 Test 添加到 PRODUCT_PACKAGES 裏面。
5) 重新 build 整個工程
注意:這個比不能卸載的多了一句
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
4、apk可以卸載恢復出場設置時能恢復
在packages/apps下面以需要預置的 APK 名字創建文件夾,以預置一個名爲Test的APK爲例:
1) 將Test.apk 放到 packages/apps/Test 下面;
2) 在packages/apps/Test下面創建文件 Android.mk,文件內容如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Module name should match apk name to be installed
LOCAL_MODULE := Test
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_CERTIFICATE := PRESIGNED
LOCAL_MODULE_PATH := $(TARGET_OUT)/vendor/operator/app
include $(BUILD_PREBUILT) 4) 打開文件 build/target/product/${Project}.mk (其中 ${Project} 表示工程名)或者是在build/target/product/core.mk文件 或者是 device/mediatek/productname/device.mk,因各自公司而易
將 Test 添加到 PRODUCT_PACKAGES 裏面
4) 重新 build 整個工程
device\mediatek\common\device.mk,將 Test 添加到 PRODUCT_PACKAGES 裏面。
PRODUCT_PACKAGES += Test
若需要apk作爲32bit的apk運行,則需要在Android.mk中定義
LOCAL_MULTILIB :=32
其中要注意的有:LOCAL_CERTIFICATE
LOCAL_CERTIFICATE := PRESIGNED //適用於app已經簽名的
LOCAL_CERTIFICATE := platform //試用於app沒有簽名的
一定要區分清楚,不然會報錯
快速合入客戶APP 到系統鏡像文件system.img中
在有些情況下 我們只是要合入某APK到System.img中(預製到系統中) 文件,然後刷系統調試一下該APP,最快的方法就是:
(1)將該APK 文件解壓,提取 lib文件(直接複製 lib 文件),
(2)進入你要合入該APP的系統APP生成路徑(如:system/app/ system/priv-app)目下,新建一個與APK文件名相同的文件夾,將該APK 文件與提取出來的 lib文件 放入此文件班夾下即可,
(3)另外需將so庫文件複製一份到out目錄下項目文件夾下的system/lib,要不然手機系統system/lib下無os庫文件
(4)執行 make snod 重新打包生成新的system.img文件 就OK
(備註)如果在第三步執行打包過程中異常了,則需要進入alps\vendor\mediatek\proprietary\frameworks\base\data\etc\pms_sysapp_removable_system_list.txt
將該APP的包名加入此文件中,
#################完整可用的示例 -- 不可卸載,無源碼,不帶OS庫文件的
# APKNAME-只需要修改的你的APK文件名字參數APKNAME,直接可用
LOCAL_PATH := $(call my-dir)
my_archs := arm x86
my_src_arch := $(call get-prebuilt-src-arch, $(my_archs))
include $(CLEAR_VARS)
LOCAL_MODULE := APKNAME
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_TAGS := optional
LOCAL_BUILT_MODULE_STEM := package.apk
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
#LOCAL_PRIVILEGED_MODULE :=
LOCAL_CERTIFICATE := PRESIGNED
#LOCAL_OVERRIDES_PACKAGES :=
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
#LOCAL_REQUIRED_MODULES :=
LOCAL_MODULE_TARGET_ARCH := $(my_src_arch)
include $(BUILD_PREBUILT)
#######################無源碼,不可卸載,帶OS庫文件的
#APKNAME 只需要修改APKNAME參數即可使用
LOCAL_PATH := $(call my-dir)
my_archs := arm arm64
my_src_arch := $(call get-prebuilt-src-arch, $(my_archs))
include $(CLEAR_VARS)
LOCAL_MODULE := APKNAME
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_TAGS := optional
LOCAL_BUILT_MODULE_STEM := package.apk
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
#LOCAL_PRIVILEGED_MODULE :=
LOCAL_CERTIFICATE := PRESIGNED
#LOCAL_OVERRIDES_PACKAGES :=
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
LOCAL_PREBUILT_JNI_LIBS := \
lib/$(my_src_arch)/libXXXX.so \
lib/$(my_src_arch)/libXXXXX.so
LOCAL_MODULE_TARGET_ARCH := $(my_src_arch)
include $(BUILD_PREBUILT)
上面的帶OS庫文件的必須將項目中的lib目錄的下兩文件名修改成arm和arm64(如果要系統位數區別的庫),
不能沿用apk解壓中的文件名稱
否則會報錯誤:
ninja: error: 'packages/apps/apkname/lib/arm64/libIxxx.so', needed by 'out/target/product/a/system/app/apkname/lib/arm64/libIxxx.so', missing and no known rule to make it