說到.mk文件,看多android源碼的童鞋會發現其中存在着繁多的mk文件。一開始不知道是幹什麼的,後來才發現這是android源碼正常編譯工作的大功臣。
習慣開發APP的童鞋,配套使用一定是一款自己拿手的IDE。那對於android源碼來說,配套使用的就是一整套mk文件。android源碼複雜,由不同功能的文件夾組成,幾乎每個模塊的根路徑下都有一個mk文件,android系統在編譯的時候,就會根據這個mk文件對此模塊進行定製化編譯。是需要編譯哪些內容,依賴什麼,編譯得到什麼,mk這種規則文件都很好的制定一個模塊編譯階段該幹什麼。mk文件還有個突出的優點,叫自動化,既然訂好了規則,編譯的時候對於每個模塊只要執行編譯就好了,像多米諾骨牌,全盤結束。
常見的編譯類型有編譯出apk,編譯出jar,編譯出二進制可執行文件,編譯出.so庫文件等等
1
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_PACKAGE_NAME := Settings
LOCAL_MODULE_TAGS := tests
LOCAL_CERTIFICATE := platform
LOCAL_STATIC_JAVA_LIBRARIES := jarlib1 jarlib2 jarlib3
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_JAVA_LIBRARIES := \
com.mstar.android \
com.cultraview.tv
include $(BUILD_PACKAGE)
##################################################
include $(CLEAR_VARS)
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := jarlib1:libs/jsoup-1.7.2.jar \
jarlib2:libs/android-support-v4.jar \
jarlib3:libs/setting.jar
include $(BUILD_MULTI_PREBUILT)
編譯.apk文件,mk中需要註明include $(BUILD_PACKAGE),前二句正常開頭,制定當前目錄,清空變量。第三句指定應用名,第四句指定編譯類型(debug or release)備註tests爲debug模式,忽視waring,正常編譯,否則佈局中有android:text=“XXX”,沒有引用string.xml的資源,會直接報錯。第四句爲引入靜態鏈接庫,導入項目libs下三方jar(此處可以留意引入靜態鏈接庫的寫法,第5句和倒數###後需要一起書寫)第6句指定需要對項目中哪些文件進行編譯,第7句指定動態鏈接庫,一般爲源碼中jar的名。
2.
LOCAL_PATH:= $(call my-dir)
# the library
# ============================================================
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_MODULE := android.policy
# MStar Android Patch Begin
# CTV Patch Begin
LOCAL_JAVA_LIBRARIES := com.mstar.android \
com.cultraview.tv
# CTV Patch End
# MStar Android Patch End
include $(BUILD_JAVA_LIBRARY)
# additionally, build unit tests in a separate .apk
include $(call all-makefiles-under,$(LOCAL_PATH))
編譯jar,mk中需要註明include $(BUILD_JAVA_LIBRARY),這邊說下第4句local module寫明爲android.policy,那最後out下生成的jar,就會看到是android.policy.jar。還有最後一句,如果要生成單元測試apk,那可以寫最後一句。
3.
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
dumpsys.cpp
LOCAL_SHARED_LIBRARIES := \
libutils \
liblog \
libbinder
ifeq ($(TARGET_OS),linux)
LOCAL_CFLAGS += -DXP_UNIX
#LOCAL_SHARED_LIBRARIES += librt
endif
LOCAL_MODULE:= dumpsys
include $(BUILD_EXECUTABLE)
編譯二進制可執行文件,比如熟悉的dumpsys指令,mk中需要註明include $(BUILD_EXECUTABLE),其中有意思的一點是mk中執行各種簡單邏輯代碼比如if。
4.
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE:= libeffectproxy
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := \
EffectProxy.cpp
LOCAL_CFLAGS+= -fvisibility=hidden
LOCAL_SHARED_LIBRARIES := liblog libcutils libutils libdl libeffects
LOCAL_C_INCLUDES := \
system/media/audio_effects/include \
bionic/libc/include \
frameworks/av/media/libeffects/factory
include $(BUILD_SHARED_LIBRARY)
編譯so庫文件,需要註明include $(BUILD_SHARED_LIBRARY)。
講了那麼多例子,無非是將不同場景中mk的用途稍微展示了下,當然mk還能做更多的作用,這裏不一一列出,隨便對源碼的研究深入,對mk的理解也會加深。
這裏再提一個mk的深入研究,mk之間是如何連串起來工作的,哪個是第一個mk,第一個mk的作用。
在android源碼根路徑下有個makefile文件,不同於普通.mk文件,它只有一句話include build/core/main.mk,也就意味主入口,mk的相關代碼都在build/core下.
Android Makefile 的引用關係是這樣的
Makefile -> build/core/main.mk -> build/core/config.mk -> build/core/envsetup.mk -> build/core/product_config.mk
這裏簡單提及一下,main.mk主要做了一些檢查工作,使用什麼shell,用什麼編譯,確定當前路徑等,接下來交給config.mk,它對普通mk文件意義非凡,比如之前看到的SRC等屬性,都是由config.mk來解析,具體工作。envsetup.mk主要對於編譯的SDK版本等一些做一個設定。product_config.mk主要引出對device.mk等的編譯。
至於爲什麼能一層一層,像多米諾骨牌一樣自動,源於mk中的一句話include $(call all-subdir-makefiles) 每當遇到這句,意味着make還需要繼續找下一級目錄下mk文件,繼續執行。