Android.mk/Android.bp 详解
Android.mk 的作用
Android.mk 是Android 编译系统中使用的 Makefile 文件,不同于传统的makefile 文件,提供了大量的内置函数;Android 下的 APP,native binary,native lib 都可以使用Android.mk 进行编译
Andoird.mk 示例如下(编译一个native binary):
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := test_android_demo
LOCAL_SRC_FILES += libutils_test.cpp test_demo.cpp\
libutilsbasic_test.cpp
LOCAL_SHARED_LIBRARIES += libutils libcutils libbase liblog
LOCAL_SHARED_LIBRARIES += libhidlbase
LOCAL_SHARED_LIBRARIES += libbinder libion \
libEGL libGLESv1_CM libGLESv2
LOCAL_C_INCLUDES +=
LOCAL_CFLAGS += -DLOG_TAG=\"test_demo\"
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE)
-
LOCAL_PATH := $(call my-dir)
每个Android.mk文件都以LOCAL_PATH固定开始,Build System提供的宏函数 my-dir,此变量返回包含的makefile的路径 -
include $(CLEAR_VARS)
作用是清除 LOCAL_PATH 变量之外的 LOCAL_XXX 变量,因为所有Android.mk 都在同一个GNU MAKE执行环境中,所有的变量都是全局的,在编译该模块之前可能编译过别的模块,产生了大量无关变量,如果不清除,会产生不可预知的错误 -
LOCAL_MODULE:=xxx
声明模块名称,名称必须唯一且不含任何空格 -
LOCAL_SRC_FILES 变量代表需要编译的文件
-
LOCAL_C_INCLUDES 设置头文件的include目录列表
LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
include $(BUILD_STATIC_LIBRARY)表示编译成静态库
include $(BUILD_SHARED_LIBRARY)表示编译成动态库
include $(BUILD_EXECUTABLE)表示编译成可执行程序
include $(BUILD_PREBUILT)表示把文件当成编译项目
LOCAL_VENDOR_MODULE := true 表示生成的lib或者bin 生成在vendor 目录下,否则是会默认生成在system 目录下, 生成在vendor 目录就需要注意VNDK的限制,为了保证AOSP 和vendor 部分的分离,system 部分的动态库是不能直接使用的
andoird.mk 的递归查找
$(call all-java-files-under, $(LOCAL_PATH)) :获取指定目录下的所有 Java 文件。
$(call all-c-files-under, $(LOCAL_PATH)) :获取指定目录下的所有 C 语言文件。
$(call all-Iaidl-files-under, $(LOCAL_PATH)) :获取指定目录下的所有 AIDL 文件。
$(call all-makefiles-under, $(LOCAL_PATH)):获取指定目录下的所有 Make 文件
-
LOCAL_MODULE_TAGS := optional
表示编译的标签,常用的有 debug, eng, user,development 或者 optional
Android.bp的作用
Android.bp的出现就是为了替换Android.mk文件;bp跟mk文件不同,它是纯粹的配置,没有分支、循环等流程控制,不能做算数逻辑运算,如果需要控制逻辑,那么只能通过Go语言编写
Android.bp 示例如下:
cc_binary {
name: "test_demo_native",
default: ["test_demo_defaults"],
clang: true,
cflags: [
"-Wall",
"-Werror"
],
shared_libs: [
"libion",
"libutils",
"libcutils",
"libbase",
"liblog",
"libhidlbase",
"libbinder",
"libEGL",
"libGLESv1_CM",
"libGLESv2"
],
src: [
"libutils_test.cpp",
"test_demo.cpp",
"libutilsbasic_test.cpp"
]
header_libs: ["libsurfaceflinger_headers"]
}
Android.bp 的注释类似于C语言,分为单行注释和多行注释两种 // 和 /**/
基本格式为:
[module type] {
name: ["name value"],
[property1name]:["property1value"]
[property2name]:["property2 value"]
}
常见的module type 类型:
- cc_binary :native 可执行文件
- cc_library_static :静态库文件
- cc_library_shared:动态库文件
- cc_test:测试 可执行文件,多用于vts 测试的makefile,生成在data 目录下
android.bp 也可以使用group 的形式使用,比如下面将src 单独定义为一个组,最后在cc_test 中进行引用:
cc_defaults {
name: ["test_demo_defaults"]
src: [
"libutils_test.cpp",
"test_demo.cpp",
"libutilsbasic_test.cpp"
]
}
在Android.bp 使用 default name 进行引用就可以了
其余typename 的含义如下:
元素 | 说明 |
---|---|
cc_library_shared | 编译成动态库,类似于Android.mk中的BUILD_SHARED_LIBRARY |
cc_binary | 编译成可执行文件,类似于Android.mk中的BUILD_EXECUTABLE |
cc_test | 编译成 google gtest 框架文件 |
name | 编译出的模块的名称,类似于Android.mk中的LOCAL_MODULE |
srcs | 源文件,类似于Android.mk中的LOCAL_SRC_FILES |
local_include_dirs | 指定路径查找头文件,类似于Android.mk中的LOCAL_C_INCLUDES |
shared_libs | 编译所依赖的动态库,类似于Android.mk中的LOCAL_SHARED_LIBRARIES |
static_libs | 编译所依赖的静态库,类似于Android.mk中的LOCAL_STATIC_LIBRARIES |
cflags | 编译flag,类似于Android.mk中的LOCAL_CFLAGS |
编译Android APP 的 Android.mk/Android.bp
- 编译 Android app 的Android.mk 文件
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_PACKAGE_NAME := xxxxx
LOCAL_VENDOR_MODULE := true
LOCAL_CERTIFICATE := platform
LOCAL_SRC_FILES := $(call all-subdir-java-files)
#LOCAL_SRC_FILES := $(call all-java-files-under,src)
LOCAL_RESOURCES_DIR := $(LOCAL_PATH)/res
LOCAL_SDK_VERSION := current
LOCAL_MIN_SDK_VERSION := 21
LOCAL_STATIC_ANDROID_LIBRARIES := \
$(ANDROID_SUPPORT_DESIGN_TARGETS) \
android-support-v4 \
android-support-v7-appcompat \
android-support-v7-cardview \
android-support-v7-recyclerview \
android-support-v17-leanback
include $(BUILD_PACKAGE)
LOCAL_CERTIFICATE := platform 表示的是用 platform 的密钥进行签名,签名的密钥会放在
build/make/target/product/security 目录下,分别是platfrom.pk8 和 platform.x509.pem文件,如果APK的签名和系统的APK签名不一致,可能会产生安装失败的情况,APK 文件可以解压缩,里面包含 meta_INF 目录表示是签过名的APK
编译APP的 Android.bp 文件
android_app {
name:"DisplayKit",
src:[
"java/**/*.java",
],
resource_dirs:[
"res",
],
certificate:"platform",
system_ext_specific := true,
platform_api:=true,
min_sdk_version := "21",
}
编译预置库的 Android.mk 文件
include $(CLEAR_VARS)
LOCAL_MODULE := mi_display
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
LOCAL_MODULE_SUFFIX := .so
LOCAL_STRIP_MODULE := false
LOCAL_MULTILIB := 64
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FIFLES := 64/mi_display.so
LOCAL_MODULE_PATH := $(PRODUCT_OUT)/system/lib64
include $(BUILD_PREBUILT)
作用是将 64/mi_display.so 编译预置到 $(PRODUCT_OUT)/system/lib64 目录下去
编译当前目录下所有模块
因为 Android 的编译系统有搜索层级的限制,可以使用下面的 makefile,编译当前目录下所有 makefile
BUILD_ITEMS ?= all
MALIDP_BUILD_DIRS := libs
MALIDP_BUILD_DIRS += users
include $(call all-named-subdir-makefiles, $(MALIDP_BUILD_DIRS))