分析aosp植入app,需要的Android.mk和Androd.bp

Android.mk

    LOCAL_PATH:= $(call my-dir)
    #清理缓存变量
    include $(CLEAR_VARS)
    #表示目标模式
    LOCAL_MODULE_TAGS := samples
    #表示源文件编译路径 这个应用里面只有java源文件
    LOCAL_SRC_FILES := $(call all-java-files-under, src)
    #表示项目包名也就是模块名,在项目中唯一
    LOCAL_PACKAGE_NAME := HelloWorld
    #指定编译sdk版本为当前版本
    LOCAL_SDK_VERSION := current
    # 使用该指令编译目标Apk.
    include $(BUILD_PACKAGE)
    #搜索编译该源码目录下所有的mk文件,如果没有可以不写
    include $(call all-makefiles-under,$(LOCAL_PATH))

简化

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := hello-jni
LOCAL_SRC_FILES := hello-jni.c

include $(BUILD_SHARED_LIBRARY)

接下来我们来一行一行的分析

LOCAL_PATH := $(call my-dir)

一般看到这种带下划线的我们就会想到配置系统环境变量,何况这里还带有明显的路径名称。没错小伙子你很上道啊,你已经有开发者的直觉了。
LOCAl_PATH这好像是在指明什么路径。
:= 做开发的同学怎么看都觉得这像是赋值语句像但是又不完全像。
$(call my-dir)好像是去的系统值并把系统环境变量中的什么位置,或者文件位置赋值给LOCAL_PATH。
答案
Android.mk 文件必须先定义 LOCAL_PATH 变量:

LOCAL_PATH := $(call my-dir)

此变量表示源文件在开发树中的位置。在这行代码中,编译系统提供的宏函数 my-dir 将返回当前目录(Android.mk 文件本身所在的目录)的路径。
下一行

include $(CLEAR_VARS)

这一行学C语言的小伙伴大惊引包,include好像是引包的意思吧,没好好学c希望学c的小伙伴看到我的错我能纠正一下我。
在继续看好像是引用了一个什么清除的包。
答案
这一行声明 CLEAR_VARS 变量,其值由编译系统提供。
CLEAR_VARS 变量指向一个特殊的 GNU Makefile,后者会清除许多 LOCAL_XXX 变量,例如 LOCAL_MODULE、LOCAL_SRC_FILES 和 LOCAL_STATIC_LIBRARIES。请注意,GNU Makefile 不会清除 LOCAL_PATH。此变量必须保留其值,因为系统在单一 GNU Make 执行环境(其中的所有变量都是全局变量)中解析所有编译控制文件。在描述每个模块之前,必须声明(重新声明)此变量。

LOCAL_MODULE    := hello-jni

每个模块名称必须唯一,且不含任何空格。编译系统在生成最终共享库文件时,会对您分配给 LOCAL_MODULE 的名称自动添加正确的前缀和后缀。例如,上述示例会生成名为 libhello-jni.so的库。

注意:如果模块名称的开头已经是 lib,则编译系统不会附加额外的 lib 前缀;而是按原样采用模块名称,并添加 .so 扩展名。因此,比如原来名为 libfoo.c 的源文件仍会生成名为 libfoo.so 的共享对象文件。此行为是为了支持 Android 平台源文件根据 Android.mk 文件生成的库;所有这些库的名称都以 lib 开头。

LOCAL_SRC_FILES := hello-jni.c

LOCAL_SRC_FILES 变量必须包含要编译到模块中的 C 和/或 C++ 源文件列表。这句话的意思就是说,我这个工程的源码路径只有一个文件,这个文件就是我这个MK文件所在目录下的hello-jni.c

include $(BUILD_SHARED_LIBRARY)

当前模块在静态链接时需要的库的名称。
Android.bp
Android.bp文件是什么

Android.bp文件首先是Android系统的一种编译配置文件,是用来代替原来的Android.mk文件的。在Android7.0以前,Android都是使用make来组织各模块的编译,对应的编译配置文件就是Android.mk。在Android7.0开始,Google引入了ninja和kati来编译,为啥引入ninja?因为随着Android越来越庞大,module越来越多,编译时间也越来越久,而使用ninja在编译的并发处理上较make有很大的提升。Ninja的配置文件就是Android.bp,Android系统使用Blueprint和Soong工具来解析Android.bp转换生成ninja文件。为了兼容老的mk配置文件,Android当初也开发了Kati 工具来转换mk文件生成ninja,目前Android Q里边,还是支持Android.mk方式的。相信在将来的版本中,会彻底让mk文件废弃,同时Kati也就淘汰了,只保留bp配置方式,所以我们要提前学习bp。Blueprint和Soong工具的源码在Android/build/目录下,我们可以通过查阅相关代码来学习!
上面是我引用的别人的说法.


image.png

语法初探

cc_library_shared {             //编译成动态库,类似于Android.mk中的BUILD_SHARED_LIBRARY
    name: "libbluetooth_jni",   //编译出的模块的名称,类似于Android.mk中的LOCAL_MODULE
    srcs: [                     //源文件,类似于Android.mk中的LOCAL_SRC_FILES
        "com_android_bluetooth_btservice_AdapterService.cpp",
        "com_android_bluetooth_hfp.cpp",
        "com_android_bluetooth_hfpclient.cpp",
        "com_android_bluetooth_a2dp.cpp",
        "com_android_bluetooth_a2dp_sink.cpp",
        "com_android_bluetooth_avrcp.cpp",
        "com_android_bluetooth_avrcp_controller.cpp",
        "com_android_bluetooth_hid.cpp",
        "com_android_bluetooth_hidd.cpp",
        "com_android_bluetooth_hdp.cpp",
        "com_android_bluetooth_pan.cpp",
        "com_android_bluetooth_gatt.cpp",
        "com_android_bluetooth_sdp.cpp",
    ],
    include_dirs: [             //用户指定的头文件查找路径,类似于Android.mk中的LOCAL_C_INCLUDES
        "libnativehelper/include/nativehelper",
        "system/bt/types",
    ],
    shared_libs: [              //编译所依赖的动态库,类似于Android.mk中的LOCAL_SHARED_LIBRARIES
        "libandroid_runtime",
        "libchrome",
        "libnativehelper",
        "libcutils",
        "libutils",
        "liblog",
        "libhardware",
    ],
    static_libs: [              //编译所依赖的静态库,类似于Android.mk中的LOCAL_STATIC_LIBRARIES
        "libbluetooth-types",
    ],
    cflags: [                   ///编译flag,类似于Android.mk中的LOCAL_CFLAGS
        "-Wall",
        "-Wextra",
        "-Wno-unused-parameter",
    ],
}

模块与示例
Android.bp 文件中的模块以模块类型开头,然后是一组格式属性:name: value,在一点上Android.bp的语法结构与JSON的语法结构相似,都是以键值对的形式编写。下面是一个简单示例:

android_app {
    name: "Provision",
    srcs: ["**/*.java"],
    platform_apis: true,
    product_specific: true,
    certificate: "platform",
}

那么接下来逐行分析这段代码

android_app {
  
}

表示该模块用于构建一个apk

name: "Provision",

如果指定了 android_app 模块类型(在代码块的开头),就需要设定该模块的name 。此设置会为模块命名,生成的 APK 将与模块名称相同,不过带有 .apk 后缀。例如,在本例中,生成的 APK 将命名为 Provision.apk

 srcs: ["**/*.java"],

srcs用于指定当前的模块编译的源码位置,*表示通配符

platform_apis: true,

设置该标记后会使用sdk的hide的api來编译。编译的APK中使用了系统级API,必须设定该值。和Android.mk中的LOCAL_PRIVATE_PLATFORM_APIS的作用相同

certificate: "platform",

Android中共有四中签名方式:

1.testkey:普通APK,默认使用该签名。
2.platform:该APK完成一些系统的核心功能。经过对系统中存在的文件夹的访问测试,这种方式编译出来的APK所在进程的UID为system。
3.shared:该APK需要和home/contacts进程共享数据。
4.media:该APK是media/download系统中的一环。

常见的模块类型

android_app

1.用于构建Android 应用程序安装包,是Android系统应用开发中常用的模块类型,与Android.mk中的BUILD_PACKAGE作用相同。

java_library

2.java_library用于将源代码构建并链接到设备的.jar文件中。默认情况下,java_library只有一个变量,它生成一个包含根据设备引导类路径编译的.class文件的.jar包。生成的jar不适合直接安装在设备上,通过会用作另一个模块的static_libs依赖项。

如果指定“installable:true”将生成一个包含“classes.dex”文件的“.jar”文件,适合在设备上安装。指定'host_supported:true'将产生两个变量,一个根据device的bootclasspath编译,另一个根据host的bootclasspath编译。

java_library_static

3.java_library_static作用等同于java_library,但是java_library_static已经过时,不推荐使用

android_library

4.android_library将源代码与android资源文件一起构建并链接到设备的“.jar”文件中。android_library有一个单独的变体,它生成一个包含根据device的bootclasspath编译的.class文件的.jar文件,以及一个包含使用aapt2编译的android资源的.package-res.apk文件。生成的apk文件不能直接安装在设备上,但可以用作android_app模块的static_libs依赖项。

cc_library

5.cc_library为device或host创建静态库或共享库。默认情况下,cc_library具有针对设备的单一变体。指定'host_supported:true'还会创建一个以主机为目标的库。与cc_library相关的模块类型还有cc_library_shared、cc_library_headers、cc_library_static等。

设置变量

在bp中可以通过=号来设定一个全局变量

src_path = ["**/*.java"]
android_app {
    name: "Provision",
    srcs: src_path,
    platform_apis: true,
    product_specific: true,
    certificate: "platform",
}

默认模块

soong提供了一系列xx_defaults模块类型,例如:cc_defaults, java_defaults, doc_defaults, stubs_defaults等等。

xx_defaults的模块提供了一组可由其它模块继承的属性。其它模块可以通过defaults:["<:default_module_name>"]来继承xx_defaults类型模块中定义的属性。xxx_defaults类型的模块可以被多个模块继承,减少我们在bp中书写重复的属性。

cc_defaults {
    name: "gzip_defaults",
    shared_libs: ["libz"],
    stl: "none",
}

cc_binary {
    name: "gzip",
    defaults: ["gzip_defaults"],
    srcs: ["src/test/minigzip.c"],
}

数据类型

Android.bp中变量和属性是强类型,变量根据第一项赋值动态变化,属性由模块类型静态设置。支持的类型为:

1.布尔值(true或 false)

2.整数 (int)

3.字符串("string")

4.字符串列表 (["string1", "string2"])

5.映射 ({key1: "value1", key2: ["value2"]})
映射可以包含任何类型的值,包括嵌套映射

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容