android 各模塊的Android.mk文件說明及如何預置app到系統中

. 常見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 文件可以分爲三類:

  1. Build系統核心 Makefile
    這類makefile定義了整個Build系統的框架,而其他所有Make文件都是在這個框架的基礎上編寫出來的。位於/build/core目錄下。
  2. 針對某個產品的Makefile
    這類makefile是針對某個產品Make文件,這些文件通常位於device/<vendor>/<product>目錄下。
  3. 針對某個模塊的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 ###

  1. build/core/main.mk:
    1. 檢查當前的編譯環境inclue build/core/下的核心makefile文件從而完成編譯環境的配置
    2. 檢索所有的BoardConfig.mkAndroidProduct.mk載入到編譯系統
    3. main.mk裏會使用python腳本遍歷AOSP下的所有模塊(AndroidProduct.mk)並include
  2. 所有模塊下的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

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章