###1. android.mk
Android.mk 用来向编译系统描述你的源代码。具体来说:该文件是GNU Makefile的一小部分,会被编译系统解析一次或多次。你可以在每一个Android.mk 中定义一个或多个模块,你也可以在几个模块中使用同一个源代码文件。编译系统为你处理许多细节问题。
Android.mk 中的内容大致可以分为3种:
- 预定义变量(例如 LOCAL_MODULE)
- 调用预定义函数(例如 $(call my-dir))
- include 预定义Android.mk文件(例如include(CLEAR_VARS))
###2. 预定义变量
1. LOCAL_PATH : 一个Android.mk file首先必须定义好LOCAL_PATH变量。它用于在开发树中查找源文件, 通常使用
LOCAL_PATH:=$(call my-dir)
来赋值, my-dir
为android编译系统中预定义的函数, 用于返回当前路径
2. LOCAL_PACKAGE_NAME : 生成package的名字(例如指定为app, 则生成app.apk), 编译apk时需要指定
3. LOCAL_MODULE : 以标识你在Android.mk文件中描述的每个模块。名称必须是唯一的,而且不包含任何空格。注意编译系统会自动产生合适的前缀和后缀,例如,一个被命名为’foo’的共享库模块,将会生成’libfoo.so’文件
4. LOCAL_IS_HOST_MODULE : 标识模块是为android编译还是为编译时使用的主机(例如)编译
- 如果该变量为true, 则编译系统内置的变量”my_prefix”值为“HOST_”, 否则为“TARGET_”
- 如果该变量为true, 则编译系统内置的变量“my_host”值为“host-”,否则为“my_host:= ”
5. LOCAL_MODULE_TAGS : 可选 “eng”, “userdebug“,“user”, ”optional”4种, 标识在对应的编译类型下才生效, 例如,赋值为“eng”则该模块只有在编译eng image时才会被编译,默认情况下, 编译类型为”eng”
注意, “optional”意思为“don’t include this”, 即在最终生成的image中不包含该模块, 使用该选项时,模块虽然会被编译, 但是不会被打包到最终的image中, 如果需要打包进去, 还需要将该模块添加到 “PRODUCT_PACKAGES” 变量中去,例如
PRODUCT_PACKAGES += \
i2c-tools
一般在模块需要编译到任何image中时, 将LOCAL_MODULE_TAGS 赋值为“optional”, 然后添加到 PRODUCT_PACKAGES 变量中去
6. LOCAL_MODULE_CLASS : 标识了所编译模块的类型, 模块的类型决定了编译模块时中间文件存放的位置, 可选的值有
- ETC :
- EXECUTABLES :
- SHARED_LIBRARIES :
- STATIC_LIBRARIES :
- FAKE :
- JAVA_LIBRARIES
- APPS :
对于recovery模块, 还有:
- RECOVERY_EXECUTABLES
- UTILITY_EXECUTABLES
7. LOCAL_MODULE_PATH : 表示模块生成的目标将最终存放的路径, 如果不指定, 默认的目标路径为
LOCAL_MODULE_PATH := $($(my_prefix)OUT$(partition_tag)_$(LOCAL_MODULE_CLASS))
例如, 对于 LOCAL_MODULE_CLASS 为 ETC 的模块, 则最终拷贝到 /system/etc中
如果不希望使用默认的路径, 则可使用 LOCAL_MODULE_PATH 来指定位置, 在指定目标位置时,”build/core/envsetup.mk”中预定义了一些位置, 其中部分如下:
TARGET_OUT_ROOT : out/target
TARGET_PRODUCT_OUT_ROOT := $(TARGET_OUT_ROOT)/product #即 out/target/product/
PRODUCT_OUT := $(TARGET_PRODUCT_OUT_ROOT)/$(TARGET_DEVICE) #即 out/target/product/xxx/
TARGET_OUT_INTERMEDIATES := $(PRODUCT_OUT)/obj #即 out/target/product/xxx/obj/
TARGET_OUT_GEN := $(PRODUCT_OUT)/gen #即 out/target/product/xxx/gen/
TARGET_OUT := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_SYSTEM) #即 out/target/product/xxx/system/
TARGET_OUT_FAKE := $(PRODUCT_OUT)/fake_packages #即 out/target/product/xxx/fake_packeges/
TARGET_OUT_DATA := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_DATA) #即 out/target/product/xxx/fake_packeges/
TARGET_OUT_CACHE := $(PRODUCT_OUT)/cache #即 out/target/product/xxx/cache/
TARGET_OUT_VENDOR := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_VENDOR) #即 out/target/product/xxx/system/vendor/
TARGET_OUT_OEM := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_OEM) #即 out/target/product/xxx/oem/
TARGET_OUT_UNSTRIPPED := $(PRODUCT_OUT)/symbols #即 out/target/product/xxx/symbols/
TARGET_ROOT_OUT := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_ROOT) #即 out/target/product/xxx/root/
TARGET_RECOVERY_OUT := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_RECOVERY) #即 out/target/product/xxx/recovery/
TARGET_OUT_EXECUTABLES := $(TARGET_OUT)/bin #即 out/target/product/xxx/bin/
TARGET_OUT_OPTIONAL_EXECUTABLES := $(TARGET_OUT)/xbin #即 out/target/product/xxx/xbin/
TARGET_OUT_JAVA_LIBRARIES := $(TARGET_OUT)/framework #即 out/target/product/xxx/framework/
TARGET_OUT_APPS := $(TARGET_OUT)/app #即 out/target/product/xxx/app/
TARGET_OUT_APPS_PRIVILEGED := $(TARGET_OUT)/priv-app #即 out/target/product/xxx/priv-app/
TARGET_OUT_ETC := $(TARGET_OUT)/etc #即 out/target/product/xxx/etc/
TARGET_OUT_DATA_APPS := $(TARGET_OUT_DATA)/app #即 out/target/product/xxx/data/app/
TARGET_OUT_VENDOR_OPTIONAL_EXECUTABLES := $(TARGET_OUT_VENDOR)/xbin #即 out/target/product/xxx/system/vendor/xbin/
TARGET_OUT_VENDOR_APPS := $(TARGET_OUT_VENDOR)/app #即 out/target/product/xxx/system/vendor/app/
TARGET_OUT_VENDOR_ETC := $(TARGET_OUT_VENDOR)/etc #即 out/target/product/xxx/syatem/vendor/etc/
TARGET_OUT_OEM_APPS := $(TARGET_OUT_OEM)/app #即 out/target/product/xxx/oem/app
TARGET_OUT_OEM_ETC := $(TARGET_OUT_OEM)/etc #即 out/target/product/xxx/oem/etc
TARGET_ROOT_OUT_BIN := $(TARGET_ROOT_OUT)/bin #即 out/target/product/xxx/root/bin
TARGET_ROOT_OUT_SBIN := $(TARGET_ROOT_OUT)/sbin #即 out/target/product/xxx/sbin
TARGET_ROOT_OUT_ETC := $(TARGET_ROOT_OUT)/etc #即 out/target/product/xxx/etc
TARGET_ROOT_OUT_USR := $(TARGET_ROOT_OUT)/usr #即 out/target/product/xxx/usr
注意在64bit的目标平台上, 在编译动态链接库时, 通常会编译64bit和32bit版本, 若编译动态链接库时,指定了LOCAL_MODULE_PATH, 则会导致打包img时, 只包含32bit版本, 且放置在/system/lib64/中, 此时应该使用LOCAL_MODULE_RELATIVE_PATH来指定同台库的目标路径
8. LOCAL_SRC_FILES : 模块的源码文件
9. LOCAL_MODULE_SUFFIX : 生成的模块的后缀,例如“.apk” “.so”等,编译系统会自动选择正确的后缀, 一般无需指定
10. LOCAL_SHARED_LIBRARIES : 指定模块依赖的动态连接库, 例如
LOCAL_SHARED_LIBRARIES := libc libcutils
11. LOCAL_STATIC_JAVA_LIBRARIES : 依赖的静态的jar包
12. LOCAL_STATIC_LIBRARY : 指定模块使用的静态库
13. LOCAL_FORCE_STATIC_EXECUTABLE : 如果模块依赖的动态库存在对应的静态库, 则会链接静态库
14. LOCAL_C_INCLUDES : 额外的C/C++头文件路径
15. LOCAL_CC : 指定c编译器,不使用默认的
16. LOCAL_CXX : 指定C++编译器,不使用默认的
17. LOCAL_CFLAGS : 为C编译器传递额外的参数(如宏定义)如
LOCAL_CFLAGS += -DLIBUTILS_NATIVE=1
18. LOCAL_CPPFLAGS : 传递额外的参数给C++编译器,如:
LOCAL_CPPFLAGS += -ffriend-injection -DLIBUTILS_NATIVE
19. LOCAL_LDLIBS : 如
LOCAL_LDLIBS += -lm –lz –lc -lcutils –lutils –llog …
20. LOCAL_LDFLAGS : 传递给链接器额外的参数,比如想传递而外的库和库路径给ld,或者传递给ld linker的一些链接参数
21. LOCAL_CPP_EXTENSION : 如果你的C++文件不是以cpp为文件后缀,你可以通过LOCAL_CPP_EXTENSION指定C++文件后缀名
22. LOCAL_CERTIFICATE : 用于指定签名时使用的KEY,如果不指定,默认使用testkey,LOCAL_CERTIFICATE可设置的值如下:
- platform
- shared
- media
- testkey
即使用 “media.pk8 media.x509.pem” “platform.pk8 platform.x509.pem” “shared.pk8 shared.x509.pem” “testkey.pk8 testkey.x509.pem”
正好对应 AndroidManifest.xml文件中的
android:sharedUserId="android.uid.system"
android:sharedUserId="android.uid.shared"
android:sharedUserId="android.media"
23. LOCAL_PREBUILT_JNI_LIBS : 指定模块依赖的jni库
24. LOCAL_MULTILIB : 在64位的android上, 如果模块需要使用32位的库, 则需要使用该变量来指定
LOCAL_MULTILIB:=32
25. LOCAL_REQUIRED_MODULES : 指定该模块所依赖的其它模块, 当该模块被安装时, 他所依赖的模块都会被安装
26. LOCAL_OVERRIDE_PACAGES : 此变量可以使其他的模块不加入编译, 即覆盖其它的模块, 例如, 有两个闹钟app: AlarmClock 和 DeskClock, 在DeskClock中指定LOCAL_OVERRIDE_PACAGES := AlarmClock, 则可阻止AlarmClock编译
###3. 预定义android.mk文件
例如:
include $(CLEAR_VARS)
实际上是 include build/core/clear_vars.mk, 该Android.mk文件中会清除LOCAL_xxx 变量,但不会清除LOCAL_PATH 变量, 因此, 通过该文件可以看到编译系统中预定义了多少种 LOCAL_XXX 变量
这些预定义的Android.mk文件定义了大量的规则, 常用的几个如下:
- include $(BUILD_EXECUTABLE) : build/core/executable.mk
- include $(BUILD_PREBUILT) : build/core/prebuilt.mk
- include $(BUILD_PACKAGE) : build/core/package.mk
- include $(BUILD_STATIC_LIBRARY) : build/core/static_library.mk
- include $(BUILD_SHARED_LIBRARY) : build/core/shared_library.mk
- include $(BUILD_JAVA_LIBRARY) : build/core/java_library.mk
- include $(BUILD_PREBUILT) : build/core/prebuilt.mk
- include $(BUILD_MULTI_PREBUILT) : build/core/multi_prebuilt.mk
- include $(BUILD_PHONY_PACKAGE) : build/core/config.mk
在编译模块时, 只需要根据需要 include 对应的规则文件即可
###4. 预定义的函数
在 build/core/definitions.mk中定义大量的Makefile 函数, 可以在Android.mk中调用
- print-vars
- my-dir
- all-makefiles-under
- first-makefiles-under
- all-subdir-makefiles
- all-named-subdir-makefiles
- all-java-files-under
- all-c-files-under
- all-subdir-c-files
- find-subdir-files
- find-subdir-subdir-files
- find-parent-file
- add-dependency
###5. Android.mk 模板
####5.1 编译可执行文件的模板
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= main.c
LOCAL_MODULE:= test
include $(BUILD_EXECUTABLE)
####5.2 编译动态库模板
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= /
helloworld.c
LOCAL_MODULE:= libtest_shared
TARGET_PRELINK_MODULES := fals
include $(BUILD_SHARED_LIBRARY)
####5.3 编译静态库模板
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= /
helloworld.c
LOCAL_MODULE:= libtest_static
include $(BUILD_STATIC_LIBRARY)
####5.4 编译apk模板
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := LocalPackage
include $(BUILD_PACKAGE)
####5.5 拷贝预编译文件模板
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := cfg.ini
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE_CLASS := ETC
LOCAL_SRC_FILES := cfg.ini
include $(BUILD_PREBUILT)
####5.6 预编译带jni lib的apk
假设在64位的android上, 需要预置一个test.apk到img中,且需要给apk打sign, apk依赖一个32位的jin lib “libtest.so”
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := test.apk
LOCAL_SRC_FILES := test.apk
LOCAL_PREBUILT_JNI_LIBS := libtest.so
LOCAL_MULTILIB := 32
include $(BUILD_PREBUILT)
预编译的apk需要的jni lib需要拷贝到 /system/lib 中