一、编译一个APK的示例
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS:= optional (user debug engtests optional samples shell_ash shell_mksh)
LOCAL_SDK_VERSION:= current
# List oflibraries to include in the package
LOCAL_STATIC_LIBRARIES:=
LOCAL_SHARED_LIBRARIES:=
LOCAL_STATIC_JAVA_LIBRARIES:=
# Build all javafiles in the java subdirectory-
LOCAL_SRC_FILES := $(call all-java-files-under, src)
# Name of theAPK to build
LOCAL_PACKAGE_NAME:= LocalPackage
LOCAL_CERTIFICATE:=
LOCAL_PROGUARD_FLAG_FILES:=
# Tell it tobuild an APK
include$(BUILD_PACKAGE)
# Use thefollowing include to make our test apk.
include $(callall-makefiles-under,$(LOCAL_PATH))
Android.mk文件首先需要指定LOCAL_PATH变量,用于查找源文件。
LOCAL_PATH:=$(call my-dir)
一般情况下Android.mk和需要编译的源文件在同一目录下,所以定义成上述形式,意思是将LOCAL_PATH变量定义成本文件所在目录路径。
Android.mk中可以定义多个编译模块,每个编译模块都是
以include $(CLEAR_VARS)开始,
以include $(BUILD_XXX)结束。
CLEAR_VARS由编译系统提供,指定让GNU MAKEFILE为你清除除LOCAL_PATH以外的所有LOCAL_XXX变量,如LOCAL_MODULE,LOCAL_SRC_FILES,LOCAL_SHARED_LIBRARIES,LOCAL_STATIC_LIBRARIES等。
include$(BUILD_STATIC_LIBRARY)表示编译成静态库。
include$(BUILD_SHARED_LIBRARY)表示编译成动态库。
include $(BUILD_STATIC_JAVA_LIBRARY)表示编译成java库。
include $(BUILD_EXECUTABLE)表示编译成可执行程序。
include $(BUILD_PACKAGE) 表示编译成应用程序。
二、APK集成第三方库
Android中使用第三方库可能有两种:java库.jar和native库.so/.a。如果做上层APK开发,可以通过Eclipse集成开发环境进行集成;如果是平台级开发,可以通过源码集成,源码集成第三方库至少有两种方式:C/C++链接方式和Android prebuilt方式。这里只讨论prebuilt方式。
Android提供了Prebuilt编译方法,两个文件prebuilt.mk和multi_prebuilt.mk,对应的方法宏是BUILD_PREBUILT和 BUILD_MULTI_PREBUILT。prebuilt.mk就是prebuilt的具体实现,它是针对独立一个文件的操作,multi_prebuilt.mk是针对多个文件的,它对多个文件进行判断,然后调用prebuilt对独立一个文件进行处理。如果直接用prebuilt.mk的话还是比较麻烦的,得仔细看好需要的宏,如果使用multi_prebuilt.mk会更方便些,很多它都帮忙处理了。
首先,prebuilt库必须向生成系统声明,需要给出模块名,指定预生成库的路径,模块类型(SHARED_LIBRARIES /STATIC_LIBRARIES)。预生成模块不生成任何东西。预生成库将会复制到$PROJECT/obj/local和复制裁剪到$PROJECT/libs/<abi>目录下。
然后在其他模块中引用预生成库。在Android.mk文件中,将预生成模块名作为LOCAL_STATIC_LIBRARIES和LOCAL_SHARED_LIBRARIES的变量值。
此外,.so还可以集成到build/core/user_tags.mk中,不过一般不建议那么做,我们应尽量减少修改系统级配置。
l 集成jar包
LOCAL_STATIC_JAVA_LIBRARIES:= libXX1 \
libXX2
######################
include$(CLEAR_VARS)
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES:= libXX1:XXX1.jar \
libXX2:XXX2.jar
include$(BUILD_MULTI_PREBUILT)
LOCAL_STATIC_JAVA_LIBRARIES取jar库的别名,可以任意取值;
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES指定prebuilt jar库的规则,格式:别名:jar文件路径。注意:别名一定要与LOCAL_STATIC_JAVA_LIBRARIES里所取的别名一致,且不含.jar;jar文件路径一定要是真实的存放第三方jar包的路径。
l 集成.so动态库
LOCAL_SHARED_LIBRARIES:= libXX
######################
include$(CLEAR_VARS)
LOCAL_PREBUILT_LIBS:= libXXX:XXX.so
include$(BUILD_MULTI_PREBUILT)
LOCAL_PREBUILT_LIBS指定prebuilt so库规则,格式:别名:so文件路径。
l 集成.a静态库
LOCAL_STATIC_LIBRARIES:= libXX
##############################
include$(CLEAR_VARS)
LOCAL_PREBUILT_LIBS:= libXX:libXX.a
include$(BUILD_MULTI_PREBUILT)
l Prebuilt示例
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE :=
LOCAL_MODULE_CLASS :=
LOCAL_MODULE_PATH := #模块安装路径
LOCAL_MODULE_TAGS :=
LOCAL_SRC_FILES :=
include $(BUILD_PREBUILT)
三、编译结果生成路径
<base_rules.mk><envsetup.mk>
每个模块在编译的时候都会产生一个编译目录和一个安装目录,编译目录就是这个模块编译以后生成的目标文件,安装目录就代表着这个模块是否会编译进文件系统,就是是否编译进IMG。
LOCAL_MODULE #模块名称
LOCAL_MODULE_STEM #模块名称,不带后缀
LOCAL_MODULE_PATH #模块安装路径
LOCAL_INSTALLED_MODULE_STEM #模块名称+后缀
LOCAL_INSTALLED_MODULE #安装路径+模块名称+后缀
built_module_path := $(intermediates) #目标文件路径
LOCAL_BUILT_MODULE_STEM #目标文件名称+后缀
LOCAL_BUILT_MODULE #目标文件路径+文件名+后缀
目标文件路径
TARGET_OUT:= $(PRODUCT_OUT)/system
TARGET_OUT_APPS:=$(TARGET_OUT)/app
TARGET_OUT_SHARED_LIBRARIES:=$(TARGET_OUT)/lib
TARGET_OUT_INTERMEDIATES:= $(PRODUCT_OUT)/obj
TARGET_OUT_STATIC_LIBRARIES:=$(TARGET_OUT_INTERMEDIATES)/lib
TARGET_OUT_INTERMEDIATE_LIBRARIES:= $(TARGET_OUT_INTERMEDIATES)/lib
TARGET_OUT_COMMON_INTERMEDIATES:= $(TARGET_COMMON_OUT_ROOT)/obj
1、如果LOCAL_MODULE_CLASS包含COMMON_MODULE_CLASS := JAVA_LIBRARIES NOTICE_FILES,则编译出的中间文件会放在:
$(TARGET_OUT_COMMON_INTERMEDIATES)/$(LOCAL_MODULE_CLASS)/$(LOCAL_MODULE)_intermediates/
TARGET_OUT_COMMON_INTERMEDIATES := out/target/common/obj
2、如果LOCAL_MODULE_CLASS不包含COMMON_MODULE_CLASS,则编译出的中间文件会放在:
$(TARGET_OUT_INTERMEDIATES)/$(LOCAL_MODULE_CLASS)/$(LOCAL_MODULE)_intermediates/
TARGET_OUT_INTERMEDIATES :=out/target/product/$PROJECT/obj
.apk安装路径:
out/target/product/$PROJECT/system/app/$MODULE.apk
.apk目标路径:
out/target/product/$PROJECT/obj/APPS/$MODULE_intermediates/package.apk
.jar/.so/.a目标路径:
out/target/product/$PROJECT/obj/JAVA_LIBRARIES/libXXX_intermediates/javalib.jar
out/target/product/$PROJECT/obj/lib/libXXX.so
out/target/product/$PROJECT/obj/SHARED_LIBRARIES/libXXX_intermediates/
out/target/product/$PROJECT/obj/STATIC_LIBRARIES/libXXX_intermediates/
out/target/common/obj/APPS/$APP_intermediates/
out/target/common/obj/JAVA_LIBRARIES/libXXX_intermediates/classes.jar
javalib.jar
四、Android编译系统模块中的LOCAL_XXX变量
LOCAL_AAPT_FLAGS |
|
LOCAL_ACP_UNAVAILABLE |
|
LOCAL_ADDITIONAL_JAVA_DIR |
|
LOCAL_AIDL_INCLUDES |
|
LOCAL_ALLOW_UNDEFINED_SYMBOLS |
|
LOCAL_ARM_MODE |
|
LOCAL_ASFLAGS |
|
LOCAL_ASSET_DIR |
|
LOCAL_ASSET_FILES | 在Android.mk文件中编译应用程序$(BUILD_PACKAGE)时设置此变量,表示资源文件,通常会定义成LOCAL_ASSET_FILES += $(call find-subdir-assets) |
LOCAL_BUILT_MODULE_STEM |
|
LOCAL_C_INCLUDES | 额外的C/C++编译头文件路径,用LOCAL_PATH表示本文件所在目录 举例如下: LOCAL_C_INCLUDES += extlibs/zlib-1.2.3 LOCAL_C_INCLUDES += $(LOCAL_PATH)/src |
LOCAL_CC | 指定C编译器 |
LOCAL_CERTIFICATE | 签名认证 |
LOCAL_CFLAGS | 为C/C++编译器定义额外的标志(如宏定义),举例:LOCAL_CFLAGS += -DLIBUTILS_NATIVE=1 |
LOCAL_CLASSPATH |
|
LOCAL_COMPRESS_MODULE_SYMBOLS |
|
LOCAL_COPY_HEADERS | install应用程序时需要复制的头文件,必须同时定义LOCAL_COPY_HEADERS_TO |
LOCAL_COPY_HEADERS_TO | install应用程序时复制头文件的目的路径 |
LOCAL_CPP_EXTENSION | 如果你的C++文件不是以cpp为文件后缀,你可以通过LOCAL_CPP_EXTENSION指定C++文件后缀名。 如:LOCAL_CPP_EXTENSION := .cc 注意统一模块中C++文件后缀必须保持一致。 |
LOCAL_CPPFLAGS | 传递额外的标志给C++编译器,如:LOCAL_CPPFLAGS += -ffriend-injection |
LOCAL_CXX | 指定C++编译器 |
LOCAL_DX_FLAGS |
|
LOCAL_EXPORT_PACKAGE_RESOURCES |
|
LOCAL_FORCE_STATIC_EXECUTABLE | 如果编译的可执行程序要进行静态链接(执行时不依赖于任何动态库),则设置LOCAL_FORCE_STATIC_EXECUTABLE:=true 目前只有libc有静态库形式,这个只有文件系统中/sbin目录下的应用程序会用到,这个目录下的应用程序在运行时通常文件系统的其它部分还没有加载,所以必须进行静态链接。 |
LOCAL_GENERATED_SOURCES |
|
LOCAL_INSTRUMENTATION_FOR |
|
LOCAL_INSTRUMENTATION_FOR_PACKAGE_NAME |
|
LOCAL_INTERMEDIATE_SOURCES |
|
LOCAL_INTERMEDIATE_TARGETS |
|
LOCAL_IS_HOST_MODULE |
|
LOCAL_JAR_MANIFEST |
|
LOCAL_JARJAR_RULES |
|
LOCAL_JAVA_LIBRARIES | 编译java应用程序和库的时候指定包含的java类库,目前有core和framework两种 多数情况下定义成:LOCAL_JAVA_LIBRARIES := core framework 注意LOCAL_JAVA_LIBRARIES不是必须的,而且编译APK时不允许定义(系统会自动添加) |
LOCAL_JAVA_RESOURCE_DIRS |
|
LOCAL_JAVA_RESOURCE_FILES |
|
LOCAL_JNI_SHARED_LIBRARIES |
|
LOCAL_LDFLAGS | 传递额外的参数给连接器(务必注意参数的顺序) |
LOCAL_LDLIBS | 为可执行程序或者库的编译指定额外的库,指定库以"-lxxx"格式,举例: LOCAL_LDLIBS += -lcurses -lpthread LOCAL_LDLIBS += -Wl,-z,origin |
LOCAL_MODULE | 生成的模块的名称(注意应用程序名称用LOCAL_PACKAGE_NAME而不是LOCAL_MODULE) |
LOCAL_MODULE_PATH | 生成模块的路径 |
LOCAL_MODULE_STEM |
|
LOCAL_MODULE_TAGS | 生成模块的标记 |
LOCAL_NO_DEFAULT_COMPILER_FLAGS |
|
LOCAL_NO_EMMA_COMPILE |
|
LOCAL_NO_EMMA_INSTRUMENT |
|
LOCAL_NO_STANDARD_LIBRARIES |
|
LOCAL_OVERRIDES_PACKAGES |
|
LOCAL_PACKAGE_NAME | APK应用程序的名称 |
LOCAL_POST_PROCESS_COMMAND |
|
LOCAL_PREBUILT_EXECUTABLES | 预编译including $(BUILD_PREBUILT)或者$(BUILD_HOST_PREBUILT)时所用,指定需要复制的可执行文件 |
LOCAL_PREBUILT_JAVA_LIBRARIES |
|
LOCAL_PREBUILT_LIBS | 预编译including $(BUILD_PREBUILT)或者$(BUILD_HOST_PREBUILT)时所用, 指定需要复制的库 |
LOCAL_PREBUILT_OBJ_FILES |
|
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES |
|
LOCAL_PRELINK_MODULE | 是否需要预连接处理(默认需要,用来做动态库优化) |
LOCAL_REQUIRED_MODULES | 指定模块运行所依赖的模块(模块安装时将会同步安装它所依赖的模块) |
LOCAL_RESOURCE_DIR |
|
LOCAL_SDK_VERSION |
|
LOCAL_SHARED_LIBRARIES | 可链接动态库 |
LOCAL_SRC_FILES | 编译源文件 |
LOCAL_STATIC_JAVA_LIBRARIES |
|
LOCAL_STATIC_LIBRARIES | 可链接静态库 |
LOCAL_UNINSTALLABLE_MODULE |
|
LOCAL_UNSTRIPPED_PATH |
|
LOCAL_WHOLE_STATIC_LIBRARIES | 指定模块所需要载入的完整静态库(这些精通库在链接是不允许链接器删除其中无用的代码) |
LOCAL_YACCFLAGS |
|
OVERRIDE_BUILT_MODULE_PATH |
|