給Android原始碼增加一個專案
從編譯中樞的角度來講,增加專案就是告訴編譯中樞一些資訊,這些資訊包括:
- 這個專案的target名稱是什麼?
- 這個專案的輸出型別是什麼?比如:apk、jar包等
- 這個專案對應的variant是什麼?
有了這些資訊後,編譯中樞就知道如何編譯該專案,並將輸出的目標打包到不同的variant產品分類中。
一、給Android原始碼增加一個C專案
下面說明如何增加一個C專案。
首先,需要選擇一個目錄,本例可以選擇external目錄。
接著,需要給該專案定義一個target名稱,這個target名稱必須是全域性唯一的,這裡可以定義為helloMake。該工程很簡單,只包含一個main.c檔案,其內容如下:
- #include <stdio.h>
- #include <stdlib.h>
- #include "hello.h"
- int main()
- {
- makePrintf("helloMake");
- return 0 ;
- }
- #include <stdio.h>
- #include <stdlib.h>
- #ifndef _HELLO_H
- #define _HELLO_H
- void makePrintf(char* str)
- {
- printf("%s" , str);
- }
- #endif
- LOCAL_PATH := $(call my-dir)
- include $(CLEAR_VARS)
- LOCAL_SRC_FILES := \
- main.c
- LOCAL_C_INCLUDES += $(LOCAL_PATH)
- LOCAL_MODULE := helloMake
- LOCAL_MODULE_TAGS := eng
- include $(BUILD_EXECUTABLE)
1、所有的C/C++原檔案必須手動新增,因為編譯中樞並沒有提供一個能夠自動從當前目錄下尋找所有C/C++檔案列表的函式。
2、由於C語言中會使用到include命令,因此,必須在mk檔案中指定標頭檔案的路徑,僅需指定專案中包含的特別路徑,而不需要指定系統標頭檔案路徑。因為系統標頭檔案路徑在編譯中樞中已經設定好了,具體是在config.mk檔案中設定的,如以下程式碼所示。如果要新增一些特別的系統路徑,可以更該build/core/config.mk檔案中SRC_HEADERS的值。
3、該專案使用的TAG值為eng,因此,僅當用戶指定的產品類別是eng時才會包含該專案。如果要讓所有類別的產品都包含該專案,可以將TAG值設定為optional,並在相應的product的配置檔案中的PRODUCT_PACKAGES變數中包含該專案即可。./vendor/xxxx/build/product/xxxx_sdk.mk
4、然後就可以編譯SDK,完成後,將新的system.img耍人裝置,啟動./adb shell,在命令列下,直接呼叫helloMake,程式將輸出helloMake。
二、給Android原始碼增加一個apk專案
新增一個apk專案可能是很多應用工程師經常遇到的問題,下面來介紹如何新增一個apk專案,該過程的原理和新增C專案相同,只是apk專案中相關的編譯變數名稱和C專案稍有不同。
首先,假設已經在Eclipse下新建了一個名稱為HelloAPK的Android應用專案,下面要做的就是要把這個專案移植進Android原始碼中。前面曾經說過,編譯中樞會搜尋Android根目錄下除out目錄外的所有子目錄,並找出Android.mk檔案作為一個子專案。因此理論上可以將HelloAPK專案放在任何目錄下,只不過為了目錄的清晰,廠商一般習慣於將自己定義的專案放到vendor下的相應目錄中。
然後,刪除HelloApk目錄下的bin和gen目錄,因為這2個目錄是Eclipse編譯的輸出目錄,而其對Android編譯系統而言是多餘的,它甚至會認為這是2個原始碼目錄。從這點上看,編譯中樞似乎需要改進一下,它應該能夠自動排除APK專案下的bin和gen目錄。
接下來,就需要新建一個Android.mk檔案,並將其放到HelloAPK目錄下,該Android.mk的內容如以下程式碼所示。
- LOCAL_PATH:= $(call my-dir)
- include $(CLEAR_VARS)
- LOCAL_MODULE_TAGS := optional
- LOCAL_SRC_FILES := $(call all-java-files-under, src)
- #LOCAL_SDK_VERSION := current
- LOCAL_PACKAGE_NAME := bright-yinjk
- LOCAL_CERTIFICATE := platform
- include $(BUILD_PACKAGE)
- include $(call all-makefiles-under,$(LOCAL_PATH))
LOCAL_MODAL_TAGS 用於指定該專案的標籤值,對於應用類子專案而言,只能指定為3種情況,分別為:optional、tests、eng,這與C專案是相同的,本例中使用的是optional。因此,對於實體裝置必須在devices/haiii/k/k.mk檔案中包含該專案,否則K產品將不會包含該,如以下程式碼所示,
- PRODUCT_PACKAGES := \
- heoolMake \
- HelloAPK
- # thirdparty packages for device
- PRODUCT_PACKAGES += \
- com.tencent.qqpinyin \
- bright-yinjk
LOCAL_PACKAGE_NAME:用於描述APK專案的名稱,而C專案中用的是LOCAL_MODULE_NAME,注意區分。
LOCAL_SDK_VERSION:用於指定該APK專案所需的SDK版本,current代表了當前Android原始碼的版本。
LOCAL_CERTIFICATE:用於指定該APK專案將使用何種簽名檔案簽名最後生成的apk檔案。系統中一共包含4種簽名檔案,分別如下:
- platform FrameWork原始碼最後將生成一個Jar包,該Jar包預設使用該型別簽名
- shared 一些系統應用程式使用該型別簽名,比如Contacts等
- user 一些私有專案使用該簽名
- tests 除錯過程中使用該簽名
至於使用何種簽名取決於專案的需要,一般當需要和特定的程式共享資料庫資源時,兩個專案必須擁有相同的簽名。
最後,使用include包含BUILD_PACKAGE命令巨集告訴編譯中樞該專案的目標是一個apk程式。
以上介紹的是以原始碼的方式新增一個專案,有些時候可能還需要以一個apk檔案的方式新增一個專案,在這種情況下,本質上新增的不是一個專案,而僅僅是一個檔案。前面講過,一個product中包含的專案分為3種,其中最後一種就是私有的專案或者檔案,而這種方式實際上就是私有的檔案。因此,需要在product相關的腳步檔案中宣告該product中包含apk檔案。本例中就應該在k.mk檔案中新增以下程式碼,其中賦值的源路徑是主機系統上的路徑,而目標路徑是裝置上的路徑,兩者使用冒號分割,如下:
- PRODUCT_COPY_FILES := \
- vendor/haiii/k/helloapk/helloapk.apk:/system/app