Android-mk-Android-bp-详解

1,704 阅读2分钟

#####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))