Android.bp基于Android 10学习笔记

2024-06-17 07:32
文章标签 android 学习 笔记 bp

本文主要是介绍Android.bp基于Android 10学习笔记,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Android.bp简介

Android 7.0之后希望用Android.bp替换Android.mk,bp简单的配置更方便Ninja 文件的产生,而Blueprint和Soong 就此产生。Android 利用Blueprint和Soong 来解析bp文件,经过最终转换为ninja files。 Blueprint和Soong都是由Golang写的项目。 从Android Nougat开始,prebuilts/go/目录下新增了Golang所需的运行环境,在编译时使用。Android.bp以及相关支持,从Android Nougat开始加入,从 Android Oreo(8.0)开始默认开启。 如果需要在Android Nougat的版本使用,需要在执行编译时添加变量: make ‘USE_SOONG=true’ Soong是以前Android基于make的编译系统的替代品。它以Android.bp文件替代Android.mk,Android.bp文件用类似JSON的简洁声明来描述需要构建的模块。

参考文档:

  • Android.bp入门指南之浅析Android.bp语法
  • Android.bp 简介
  • Android.bp学习笔记

再来说一说跟着Android版本相应的发展演变过程:

  1. Android 7.0引入ninja和kati
  2. Android 8.0使用Android.bp来替换Android.mk,引入Soong
  3. Android 9.0强制使用Android.bp

转换关系

在这里插入图片描述

通过Kati将Android.mk转换成ninja格式的文件,通过Blueprint+Soong将Android.bp转换成ninja格式的文件,通过androidmk将将Android.mk转换成Android.bp,但针对没有分支、循环等流程控制的Android.mk才有效。

这里涉及到Ninja, kati, Soong, bp概念,接下来分别简单介绍一下。

  • Ninja

ninja是一个编译框架,会根据相应的ninja格式的配置文件进行编译,但是ninja文件一般不会手动修改,而是通过将Android.bp文件转换成ninja格文件来编译。

  • Android.bp

Android.bp的出现就是为了替换Android.mk文件。bp跟mk文件不同,它是纯粹的配置,没有分支、循环等流程控制,不能做算数逻辑运算。如果需要控制逻辑,那么只能通过Go语言编写。

  • Soong

Soong类似于之前的Makefile编译系统的核心,负责提供Android.bp语义解析,并将之转换成Ninja文件。Soong还会编译生成一个androidmk命令,用于将Android.mk文件转换为Android.bp文件,不过这个转换功能仅限于没有分支、循环等流程控制的Android.mk才有效。

  • Blueprint

Blueprint是生成、解析Android.bp的工具,是Soong的一部分。Soong负责Android编译而设计的工具,而Blueprint只是解析文件格式,Soong解析内容的具体含义。Blueprint和Soong都是由Golang写的项目,从Android 7.0,prebuilts/go/目录下新增Golang所需的运行环境,在编译时使用。

  • Kati

kati是专为Android开发的一个基于Golang和C++的工具,主要功能是把Android中的Android.mk文件转换成Ninja文件。代码路径是build/kati/,编译后的产物是ckati。

Android.bp语法初识

  • 例子1
cc_library_shared {				//编译成动态库,类似于Android.mk中的BUILD_SHARED_LIBRARYname: "libbluetooth_jni",	//编译出的模块的名称,类似于Android.mk中的LOCAL_MODULEsrcs: [ 					//源文件,类似于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",],
}
  • 例子2
cc_binary {             //编译成可执行文件,cc_library_shared编译成动态库name: "bt_test",    //编译出的可执行文件的名字为bt_testvendor: true,       //编译出来放在/vendor目录下(默认是放在/system目录下)srcs: ["bt_test.cpp"], //源文件,格式["a.cpp", "b.cpp"]cflags: ["-Wall","-Werror","-Wno-unused-parameter",],                    //编译flaginclude_dirs: ["hardware/interfaces/halnode/1.0/default",    //用户值定的头文件查找路径],shared_libs: [       //编译依赖的动态库"liblog","libutils","libhidltransport","android.hardware.halnode@1.0","libhidlbase","libbase",],
}
  • 例子3

srcs 属性以字符串列表的形式指定用于编译模块的源文件。您可以使用模块引用语法 “:” 来引用生成源文件的其他模块的输出,如 genrule 或 filegroup。是不是感觉一头雾水,好吗,还是上实例说明:

~/ssd/qcom_64/msm8953-9$ cd frameworks/base/core/java/
~/ssd/qcom_64/msm8953-9/frameworks/base/core/java$ vi Android.bpfilegroup {name: "IKeyAttestationApplicationIdProvider.aidl",srcs: ["android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl"],
}filegroup {name: "IDropBoxManagerService.aidl",srcs: ["com/android/internal/os/IDropBoxManagerService.aidl"],~/ssd/qcom_64/msm8953-9/frameworks/base/core$ cd ..
~/ssd/qcom_64/msm8953-9/frameworks/base$ vi libs/services/Android.bpcc_library_shared {name: "libservices",srcs: [":IDropBoxManagerService.aidl","src/os/DropBoxManager.cpp","src/os/StatsDimensionsValue.cpp","src/os/StatsLogEventWrapper.cpp",],  shared_libs: ["libbinder","liblog","libcutils","libutils",],

模块

从前面的列子可以看出定义一个模块从模块的类型开始,模块有不同的类型,如前面例子中的cc_library_shared,当然类型还有很多种,譬如cc_binary android_app cc_library_static等等。模块包含一些属性格式为“property-name:property-value”,其中name属性必须指定,其属性值必须是全局唯一的。

其中默认模块可用于在多个模块中重复相同的属性,是不是用文字表达很模糊,好吗,上实例:

cc_defaults {//		//默认模块名称name: "default_module",shared_libs: ["libz"],stl: "none",
}
cc_binary {name: "test1",defaults: ["default_module"],	//引用默认模块名称srcs: ["src/test/test.c"],
}

类型

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

  • 布尔值(true 或 false)
  • 整数 (int)
  • 字符串 (“string”)
  • 字符串列表 ([“string1”, “string2”])
  • 映射 ({key1: “value1”, key2: [“value2”]})
  • 映射可以包含任何类型的值,包括嵌套映射。列表和映射可能在最后一个值后面有终止逗号。

其它可用选项

  • subdirs = [“ndk”]   //指定进入下层ndk目录进行编译

  • export_include_dirs: [   //从其他模块添加头文件检索路径 “include”, “include/camera” ],

  • export_shared_lib_headers: [“libcamera_metadata”],

  • local_include_dirs: [“aidl”],   //如果从当前目录添加路径时使用,将./aidl目录加入头文件的搜索路径

  • static_libs: [“libupdater”],   //指定对库libupdater进行静态链接 static_executable: true,

变量

Android.bp文件可包含顶级变量赋值:

test_srcs = ["src/test.c"],
cc_binary {name: "test",srcs: test_srcs,
}

变量范围限定为声明它们的文件的其余部分,以及任何子蓝图文件。变量是不可变的,但有一个例外 —— 它们可以附上+= 赋值,但仅在变量被引用之前。

注释

我们知道Android.mk中可以进行注释,当然Android.bp里面也可以,Android.mk中使用"#"然后添加注释,Android.bp使用单行注释//和多行注释/* */两种方式。

运算符

可以使用 + 运算符附加字符串、字符串列表和映射。可以使用 + 运算符对整数求和。附加映射会生成两个映射中键的并集,并附加在两个映射中都存在的所有键的值。

###条件语句
Soong 不支持 Android.bp 文件中的条件语句。但是,编译规则中需要条件语句的复杂问题将在 Go(在这种语言中,您可以使用高级语言功能,并且可以跟踪条件语句引入的隐式依赖项)中处理。大多数条件语句都会转换为映射属性,其中选择了映射中的某个值并将其附加到顶级属性。

例如,要支持特定于架构的文件,请使用以下命令:

cc_library {...srcs: ["generic.cpp"],arch: {arm: {srcs: ["arm.cpp"],},x86: {srcs: ["x86.cpp"],},},
}
system/core/libusbhost$ cat Android.bp cc_library {name: "libusbhost",vendor_available: true,vndk: {enabled: true,},host_supported: true,srcs: ["usbhost.c"],cflags: ["-Werror"],export_include_dirs: ["include"],target: {   //相当于ifandroid: {    //编译Android上运行的程序 相当于ifcflags: ["-g","-DUSE_LIBLOG",],shared_libs: ["liblog"],},darwin: {    //编译darwin上运行的程序enabled: false,},},
}

支持模块类型

Android.bp可以支持android_app、cc_binary、cc_binary_host等多种类型,具体定义在Android源码的build/soong/androidmk/cmd/androidmk/android.go可以查看,具体如下:

var moduleTypes = map[string]string{"BUILD_SHARED_LIBRARY":        "cc_library_shared","BUILD_STATIC_LIBRARY":        "cc_library_static","BUILD_HOST_SHARED_LIBRARY":   "cc_library_host_shared","BUILD_HOST_STATIC_LIBRARY":   "cc_library_host_static","BUILD_HEADER_LIBRARY":        "cc_library_headers","BUILD_EXECUTABLE":            "cc_binary","BUILD_HOST_EXECUTABLE":       "cc_binary_host","BUILD_NATIVE_TEST":           "cc_test","BUILD_HOST_NATIVE_TEST":      "cc_test_host","BUILD_NATIVE_BENCHMARK":      "cc_benchmark","BUILD_HOST_NATIVE_BENCHMARK": "cc_benchmark_host","BUILD_JAVA_LIBRARY":             "java_library","BUILD_STATIC_JAVA_LIBRARY":      "java_library_static","BUILD_HOST_JAVA_LIBRARY":        "java_library_host","BUILD_HOST_DALVIK_JAVA_LIBRARY": "java_library_host_dalvik","BUILD_PACKAGE":                  "android_app",
}

支持预编译类型

Android.bp可以支持多种预编译类型,具体定义在Android源码的build/soong/androidmk/cmd/androidmk/android.go可以查看,如下图所示:

var prebuiltTypes = map[string]string{"SHARED_LIBRARIES": "cc_prebuilt_library_shared","STATIC_LIBRARIES": "cc_prebuilt_library_static","EXECUTABLES":      "cc_prebuilt_binary","JAVA_LIBRARIES":   "prebuilt_java_library",
}

常用工具

(1)bpfmt 一个是格式化工具bpfmt。 与gofmt类似,可以格式化Blueprint文件。 (其实,代码基本上都是从gofmt复制而来。)eg 格式化当前目录及其递归子目录下的所有Android.bp:

wugn # bpfmt -w .

(2)androidmk 另一个是androidmk,负责转换Android.mk为Android.bp。

wugn: # androidmk Android.mk > Android.bp

这篇关于Android.bp基于Android 10学习笔记的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1068820

相关文章

Android中Dialog的使用详解

《Android中Dialog的使用详解》Dialog(对话框)是Android中常用的UI组件,用于临时显示重要信息或获取用户输入,本文给大家介绍Android中Dialog的使用,感兴趣的朋友一起... 目录android中Dialog的使用详解1. 基本Dialog类型1.1 AlertDialog(

Android Kotlin 高阶函数详解及其在协程中的应用小结

《AndroidKotlin高阶函数详解及其在协程中的应用小结》高阶函数是Kotlin中的一个重要特性,它能够将函数作为一等公民(First-ClassCitizen),使得代码更加简洁、灵活和可... 目录1. 引言2. 什么是高阶函数?3. 高阶函数的基础用法3.1 传递函数作为参数3.2 Lambda

Android自定义Scrollbar的两种实现方式

《Android自定义Scrollbar的两种实现方式》本文介绍两种实现自定义滚动条的方法,分别通过ItemDecoration方案和独立View方案实现滚动条定制化,文章通过代码示例讲解的非常详细,... 目录方案一:ItemDecoration实现(推荐用于RecyclerView)实现原理完整代码实现

Android App安装列表获取方法(实践方案)

《AndroidApp安装列表获取方法(实践方案)》文章介绍了Android11及以上版本获取应用列表的方案调整,包括权限配置、白名单配置和action配置三种方式,并提供了相应的Java和Kotl... 目录前言实现方案         方案概述一、 androidManifest 三种配置方式

Java进阶学习之如何开启远程调式

《Java进阶学习之如何开启远程调式》Java开发中的远程调试是一项至关重要的技能,特别是在处理生产环境的问题或者协作开发时,:本文主要介绍Java进阶学习之如何开启远程调式的相关资料,需要的朋友... 目录概述Java远程调试的开启与底层原理开启Java远程调试底层原理JVM参数总结&nbsMbKKXJx

Android WebView无法加载H5页面的常见问题和解决方法

《AndroidWebView无法加载H5页面的常见问题和解决方法》AndroidWebView是一种视图组件,使得Android应用能够显示网页内容,它基于Chromium,具备现代浏览器的许多功... 目录1. WebView 简介2. 常见问题3. 网络权限设置4. 启用 JavaScript5. D

Android如何获取当前CPU频率和占用率

《Android如何获取当前CPU频率和占用率》最近在优化App的性能,需要获取当前CPU视频频率和占用率,所以本文小编就来和大家总结一下如何在Android中获取当前CPU频率和占用率吧... 最近在优化 App 的性能,需要获取当前 CPU视频频率和占用率,通过查询资料,大致思路如下:目前没有标准的

Android开发中gradle下载缓慢的问题级解决方法

《Android开发中gradle下载缓慢的问题级解决方法》本文介绍了解决Android开发中Gradle下载缓慢问题的几种方法,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、网络环境优化二、Gradle版本与配置优化三、其他优化措施针对android开发中Gradle下载缓慢的问

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

Android里面的Service种类以及启动方式

《Android里面的Service种类以及启动方式》Android中的Service分为前台服务和后台服务,前台服务需要亮身份牌并显示通知,后台服务则有启动方式选择,包括startService和b... 目录一句话总结:一、Service 的两种类型:1. 前台服务(必须亮身份牌)2. 后台服务(偷偷干