Android.bp学习笔记
一、简介
1.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的简洁声明来描述需要构建的模块。
2.例子1
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",
],
}
2.其它可用选项
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,
4.官方最全解释
Android.bp Build Docs (android-8.0.0-r9):http://note.qidong.name/demo/soong_build/
5.变量
Android.bp文件可包含顶级变量赋值:
test_srcs = ["src/test.c"], cc_binary { name: "test", srcs: test_srcs, }
变量范围限定为声明它们的文件的其余部分,以及任何子蓝图文件。变量是不可变的,但有一个例外 —— 它们可以附上+= 赋值,但仅在变量被引用之前。
6.注释
注释方式,与Golang类似。 支持行注释//与块注释/* block */。
7.操作符
除了赋值的 = 以外,只有 + 。
8.默认模块
默认模块可用于在多个模块中重复相同的属性。
cc_defaults { name: "test_defaults", shared_libs: ["libz"], stl: "none", } cc_binary { name: "test1", defaults: ["test_defaults"], srcs: ["src/test/test1.c"], }
9.常用工具
(1) bpfmt 一个是格式化工具bpfmt。 与gofmt类似,可以格式化Blueprint文件。 (其实,代码基本上都是从gofmt复制而来。)eg 格式化当前目录及其递归子目录下的所有Android.bp: # bpfmt -w .
(2) androidmk 另一个是androidmk,负责转换Android.mk为Android.bp, eg: # androidmk Android.mk > Android.bp
10.工具链关系
Android.mk、Android.bp、Soong、Blueprint、Ninja 简单的方式表达这几个概念之间的作用关系
Android.bp --> Blueprint --> Soong --> Ninja
Makefile or Android.mk --> kati --> Ninja Android.mk --> Soong --> Blueprint --> Android.bp
二、例子
1. 较完整使用例子
$ cat Android.bp cc_binary { name: "test_service", init_rc: ["test_service.rc"], //cpp源文件包含src目录下的cpp文件以及src目录下子目录下的cpp文件 srcs: ["src/**/*.cpp"], //配置绝对路径,访问其它模块的头文件(应该要使用的有没导出) include_dirs: [ "external/libpng/include", ], //本地目录下的头文件路径,导出各子目录下的头文件 local_include_dirs: [ "include","src/utils/include","src/config/include", ], //特殊头文件包含方法 header_libs: [ "lib-eventid-headers", ], //指定动态链接库 shared_libs: [ "libcutils", "libutils", "libbase", "libbinder", "liblog", "libhidlbase", "android.hardware.graphic@2.0", ], //指定静态链接库 static_libs: [ "libdmabufinfo", "libjsoncpp", ], //指定编译标志 cflags: [ "-Wall", "-Werror", "-Wno-unused-parameter", //不对没有使用的变量报错 "-Wunused", "-D__ANDROID_15__", ], product_variables: { // enable debug for userdebug/eng/userdev build debuggable: { cflags: [ "-DENABLE_DEBUG_ALL", ], }, userdev: { cppflags: [ "-DENABLE_DEBUG_LIMIT", ], }, }, }
2. 使用 cc_defaults
cc_binary { name: "sock_server", srcs: [ "android_sock_server.cpp", ], defaults: ["cc_sock_build_defaults"], } cc_binary { name: "sock_client", srcs: [ "android_sock_client.cpp", ], defaults: ["cc_sock_build_defaults"], } cc_defaults { name: "cc_sock_build_defaults", cflags: [ "-Wall", "-Werror", "-Wno-unused-parameter", "-Wunused", "-D__ANDROID_15__", ], static_libs: [ "libc", "libcutils", "liblog", ], static_executable: true, }
3. 常用cc_flags
注: 经常由于这些小细节编译报错
cflags: [ "-Wall", // 启用基本警告 "-Werror", // 将警告视为错误 "-Wno-unused-function", // 忽略未使用函数警告 "-Wno-unused-parameter", // 忽略未使用参数 "-Wno-unused-variable", // 忽略未使用变量 ],
4. 头文件引用处理
4.1 导出给其它模块使用
总结:
(1) export_include_dirs 是最基础的头文件导出方式,适用于所有包含头文件的 C/C++ 模块,包括 cc_library_shared、cc_library_static 甚至纯头文件库 cc_library_headers。
(2) cc_library_headers 是纯头文件导出模块,编译后会生成对应的 .a 文件。
(3) export_shared_lib_headers 是处理头文件的间接依赖。有严格的适用范围:它只能用于动态库模块(cc_library_shared),且仅能转发动态库依赖(通过 shared_libs 声明的库)的头文件。对于静态库依赖,需使用 export_static_lib_headers;对于纯头文件库,则需用 export_header_lib_headers。
例子:
cc_library_headers { //创建一个名为 libtest_headers 的头文件模块,导出 include 目录下的所有头文件
name: "libtest_headers",
export_include_dirs: ["include"]
}
其他模块通过 header_libs: ["libtest_headers"] 引用后,即可直接 #include "test.h"(假设 test.h 位于 include 目录下)。但是实测并不好用,编译会报错"module my_test missing dependencies: libtest_headers"。
下面方法好用:
cc_library_shared { name: "libtest", ... export_include_dirs: ["include"], //导出include目录下的头文件 }
使用模块引用libtest库会自动包含头文件,my_test的实现中直接 #include <test.h> 即可。
cc_binary { name: "my_test", ... shared_libs: [ "libtest", ], }
还有一个 export_shared_lib_headers,它的作用是“转发依赖”的机制,它让当前模块将自己依赖的其他动态库的头文件间接暴露给下游。例如,若 libtest 依赖 libtinyxml2 并设置 export_shared_lib_headers: ["libtinyxml2"],那么引用 libtest 的模块不仅能使用 libtest 自身的头文件,还能直接包含 libtinyxml2 的头文件,无需单独声明对 libtinyxml2 的依赖。
4.2 导出给内部模块使用
导出本地include目录下的所有头文件给本模块使用。
cc_library_shared { name: "libtest", ... local_include_dirs: ["include"], }
5. 源文件包含处理
srcs: [ "page-types.c", //当前目录下的此文件 "api/**/*.c", //api目录下的及其子目录下的所有.c文件 ],
6. 宏定义
例子:
cflags: [ "-Wall", "-Werror", "-DAndroid13", //定义宏 #define Android13 "-DLOG_TAG=\"CaEvs\"" //定义宏 #define LOG_TAG "CaEvs" ]
posted on 2019-03-25 18:56 Hello-World3 阅读(31619) 评论(0) 收藏 举报
浙公网安备 33010602011771号