文章出处:http://blog.csdn.net/shift_wwx
前言:了解四大组件之前也有必要熟悉项目的AndroidManifest.xml基础知识,还要熟悉Android.mk基础知识,这两个应该是前提,个人习惯拿到一个没有看过一个应用的程序,首先看的是Manifest和makefile。之前已经写了一篇关于Manifest的文章:《Android基础总结之四:AndroidManifest.xml详解》,这里做一下makefile的小结。
一、举例说明
一个Android.mk file用来向编译系统描述你的源代码。具体来说:该文件是GNU Makefile的一小部分,会被编译系统解析一次或多次。你可以在每一个Android.mk file中定义一个或多个模块,你也可以在几个模块中使用同一个源代码文件。选项参考以下文件:build/core/config.mk,默认的值在以下文件中定义:build/core/base_rules.mk。编译系统为你处理许多细节问题。例如,你不需要在你的Android.mk中列出头文件和依赖文件。NDK编译系统将会为你自动处理这些问题。
首先看个小例子:
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := $(call all-subdir-java-files) LOCAL_PACKAGE_NAME := AlarmClock include $(BUILD_PACKAGE)
1. LOCAL_PATH := $(call my-dir) ,一个Android.mk file首先必须定义好LOCAL_PATH变量。它用于在开发树中查找源文件。在这个例子中,宏函数‘my-dir’, 由编译系统提供,用于返回当前路径(即包含Android.mk file文件的目录)。
其中my-dir定义在build/core/definitions.mk中,code如下:
# Figure out where we are. define my-dir $(strip \ $(eval LOCAL_MODULE_MAKEFILE := $$(lastword $$(MAKEFILE_LIST))) \ $(if $(filter $(CLEAR_VARS),$(LOCAL_MODULE_MAKEFILE)), \ $(error LOCAL_PATH must be set before including $$(CLEAR_VARS)) \ , \ $(patsubst %/,%,$(dir $(LOCAL_MODULE_MAKEFILE))) \ ) \ ) endef
2. include $( CLEAR_VARS),CLEAR_VARS由编译系统提供,指定让GNU MAKEFILE为你清除许多LOCAL_XXX变量(例如 LOCAL_MODULE, LOCAL_SRC_FILES, LOCAL_STATIC_LIBRARIES, 等等...),除LOCAL_PATH 。这是必要的,因为所有的编译控制文件都在同一个GNU MAKE执行环境中,所有的变量都是全局的。
CLEAR_VARS定义在build/core/config.mk中,code如下:
CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.mk
查看clear_vars.mk就会知道CLEAR_VARS的具体作用了:
LOCAL_MODULE:= LOCAL_MODULE_PATH:= LOCAL_MODULE_STEM:= LOCAL_DONT_CHECK_MODULE:= LOCAL_CHECKED_MODULE:= LOCAL_BUILT_MODULE:= LOCAL_BUILT_MODULE_STEM:= OVERRIDE_BUILT_MODULE_PATH:= LOCAL_INSTALLED_MODULE:= LOCAL_UNINSTALLABLE_MODULE:= LOCAL_INTERMEDIATE_TARGETS:= LOCAL_UNSTRIPPED_PATH:= LOCAL_MODULE_CLASS:= LOCAL_MODULE_SUFFIX:= LOCAL_PACKAGE_NAME:= LOCAL_OVERRIDES_PACKAGES:= LOCAL_EXPORT_PACKAGE_RESOURCES:= LOCAL_MANIFEST_PACKAGE_NAME:= LOCAL_REQUIRED_MODULES:= LOCAL_ACP_UNAVAILABLE:= LOCAL_MODULE_TAGS:=
将除LOCAL_PATH之外的所有LOCAL都置空。
3. LOCAL_SRC_FILES :=$(call all-subdir-java-files),LOCAL_SRC_FILES变量必须包含将要编译打包进模块中的JAVA、C或C++源代码文件。
call all-subdir-java-files定义在build/core/definitions.mk中,code如下:
define all-subdir-java-files $(call all-java-files-under,.) endef
4. LOCAL_PACKAGE_NAME := AlarmClock,LOCAL_PACKAGE_NAME指的是生成android基本应用程序,apk包。同LOCAL_MODULE
5. include $(BUILD_PACKAGE),BUILD_PACKAGE和CLEAR_VARS一样也是在build/core/config.mk下定义的,code如下:
BUILD_PACKAGE:= $(BUILD_SYSTEM)/package.mk
最后的include是生成目标的最关键所在,例如,如果要生成apk,那么就要include $(BUILD_PACKAGE);如果要生成java的jar包,那么就要include $(BUILD_STATIC_JAVA_LIBRARY),等等......下面会慢慢介绍。
这些BUILD_***都会在/system/core/config.mk中定义的,如下:
# ############################################################### # Build system internal files # ############################################################### BUILD_COMBOS:= $(BUILD_SYSTEM)/combo CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.mk BUILD_HOST_STATIC_LIBRARY:= $(BUILD_SYSTEM)/host_static_library.mk BUILD_HOST_SHARED_LIBRARY:= $(BUILD_SYSTEM)/host_shared_library.mk BUILD_STATIC_LIBRARY:= $(BUILD_SYSTEM)/static_library.mk BUILD_RAW_STATIC_LIBRARY := $(BUILD_SYSTEM)/raw_static_library.mk BUILD_SHARED_LIBRARY:= $(BUILD_SYSTEM)/shared_library.mk BUILD_EXECUTABLE:= $(BUILD_SYSTEM)/executable.mk BUILD_RAW_EXECUTABLE:= $(BUILD_SYSTEM)/raw_executable.mk BUILD_HOST_EXECUTABLE:= $(BUILD_SYSTEM)/host_executable.mk BUILD_PACKAGE:= $(BUILD_SYSTEM)/package.mk BUILD_PHONY_PACKAGE:= $(BUILD_SYSTEM)/phony_package.mk BUILD_HOST_PREBUILT:= $(BUILD_SYSTEM)/host_prebuilt.mk BUILD_PREBUILT:= $(BUILD_SYSTEM)/prebuilt.mk BUILD_MULTI_PREBUILT:= $(BUILD_SYSTEM)/multi_prebuilt.mk BUILD_JAVA_LIBRARY:= $(BUILD_SYSTEM)/java_library.mk BUILD_STATIC_JAVA_LIBRARY:= $(BUILD_SYSTEM)/static_java_library.mk BUILD_HOST_JAVA_LIBRARY:= $(BUILD_SYSTEM)/host_java_library.mk BUILD_DROIDDOC:= $(BUILD_SYSTEM)/droiddoc.mk BUILD_COPY_HEADERS := $(BUILD_SYSTEM)/copy_headers.mk BUILD_NATIVE_TEST := $(BUILD_SYSTEM)/native_test.mk BUILD_HOST_NATIVE_TEST := $(BUILD_SYSTEM)/host_native_test.mk
二、各种mk小结
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) # Build all java files in the java subdirectory LOCAL_SRC_FILES := $(call all-subdir-java-files) # Any libraries that this library depends on LOCAL_JAVA_LIBRARIES := android.test.runner # The name of the jar file to create LOCAL_MODULE := sample # Build a static jar file. include $(BUILD_STATIC_JAVA_LIBRARY)
LOCAL_PATH := $(call my-dir) #include $(CLEAR_VARS) LOCAL_SRC_FILES := main.c LOCAL_MODULE := test_exe #LOCAL_C_INCLUDES := #LOCAL_STATIC_LIBRARIES := #LOCAL_SHARED_LIBRARIES := include $(BUILD_EXECUTABLE)
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := \ helloworld.c LOCAL_MODULE:= libtest_static #LOCAL_C_INCLUDES := #LOCAL_STATIC_LIBRARIES := #LOCAL_SHARED_LIBRARIES := include $(BUILD_STATIC_LIBRARY)
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := helloworld.c LOCAL_MODULE := libtest_shared TARGET_PRELINK_MODULES := false #LOCAL_C_INCLUDES := #LOCAL_STATIC_LIBRARIES := #LOCAL_SHARED_LIBRARIES := include $(BUILD_SHARED_LIBRARY)
三、常用变量小结
(1) LOCAL_PATH: 这个变量用于给出当前文件的路径。必须在 Android.mk 的开头定义,可以这样使用:LOCAL_PATH := $(call my-dir) 这个变量不会被$(CLEAR_VARS)清除,因此每个 Android.mk 只需要定义一次(即使在一个文件中定义了几个模块的情况下)。
user: 指该模块只在user版本下才编译
eng: 指该模块只在eng版本下才编译
tests: 指该模块只在tests版本下才编译
optional:指该模块在所有版本下都编译
四、编译流程小结
我们知道,在编译android系统的时候,会用到make命令,那么必须用到对应的Makefile文件。
我们可以在根目录中找到这样的Makefile文件,打开一看:
### DO NOT EDIT THIS FILE ### include build/core/main.mk ### DO NOT EDIT THIS FILE ###了解makefile的知道所有的定义、执行都应该在main.mk中。
很简单就能找到config.mk,这个是个很关键的makefile,其中不但包含了product的相关变量定义,和所有mk变量的定义,也包含了具体的执行mk。
因为mk文件很多,有的人会问,一般这些都是系统的makefile,device或者vendor下面的mk是什么时候调用到的呢?是最后还是最开始?
这些都可以在config.mk中找到结果。
在config.mk中很快就能找到produc_config.mk,对的,这就是关于product的所有配置、定义、链接。其中最关键的就是AndroidProduct.mk,这里会寻找除了build下的AndroidProduct.mk,还会到device或者vendor下面找,会找到所有定义PRODUCT_MAKEFILES的地方,并且执行。这个时候就进入了product的mk中了。
这里写的只是一些小结,如果想要详细了解,还是需要多看看资料、书籍。