Android.bp基于Android10学习笔记
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版本相应的发展演变过程:
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_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",
],android学习教程
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_test
vendor: true, //编译出来放在/vendor⽬录下(默认是放在/system⽬录下)
srcs: ["bt_test.cpp"], //源⽂件,格式["a.cpp", "b.cpp"]
cflags: [
"-Wall",
"-Werror",
"-Wno-unused-parameter",
], //编译flag
include_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.bp
filegroup {
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.bp
cc_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(在这种语⾔中,您可以使⽤⾼级语⾔功能,并且可以跟踪条件语句引⼊的隐式依赖项)中处理。⼤多数条件语句都会转换为映射属性,其中选择了映射中的某个值并将其附加到顶级属性。
例如,要⽀持特定于架构的⽂件,请使⽤以下命令:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论