说到.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文件,继续执行。