前言:

随着android工程越来越大,包含的module越来越多,以makefile组织的项目编译花费的时间越来越多。谷歌在7.0开始引入了ninja进行编译系统的组织。相对于make来说Ninja 在大的项目管理中速度和并行方面有突出的优势,因此谷歌采用了Ninja 来取代之前使用的make。

Android 7.0 之后再很多地方出现了Android.bp的文件,也不清楚这个后缀是什么意思,本文主要是介绍其由来和简单的语法和其使用方法,以及与其相关的Blueprint 和Soong。

 

Blueprint 和Soong

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'

Android 提供了source code 目录为 build/:

经过试验表明,soong处理后的bp文件生成build.ninja的同时还包含out/soong/Android-aosp_arm.mk,这个文件是编译完成后模块的安装脚本,负责将模块安装到对应位置。比如我们现在处理的vndk相关vendor处理就是在这个目录下进行的。

在out/soong目录下有两个文件.minibootstrap/build.ninja 和.bootstrap/build.ninja两个目录。.minibootstrap/build.ninja 主要是用来编译blueprint和生成.bootstrap/build.ninja。而.bootstrap/build.ninja主要是生成 soong相关工具和out/soong/build.ninja文件

Soong是以前Android基于make的编译系统的替代品。它以Android.bp文件替代Android.mk,Android.bp文件用类似JSON的简洁声明来描述需要构建的模块。

 

Android.bp:

Android.bp文件设计得非常简洁。没有条件或控制流语言(任何复杂性都在用Go编写的构建逻辑中被处理)。Android.bp文件的语法和语义在可能的情况下有意类似于 Bazel构建文件。

详细的Android.bp 的描述文档看:http://note.qidong.name/demo/soong_build/

语法:

Blueprint文件的语法比较简单,毕竟只是配置文件。

1、模块

Android.bp文件中的模块以模块类型开头,后跟一组name: value格式的属性:

cc_binary {    name: "gzip",    srcs: ["src/test/minigzip.c"],    shared_libs: ["libz"],    stl: "none",}

每个模块必须有name属性,且其值在所有Android.bp文件中必须是唯一的。
关于可用模块类型及其属性列表,参见$OUT_DIR/soong/.bootstrap/docs/soong_build.html.

2、变量

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

gzip_srcs = ["src/test/minigzip.c"],cc_binary {    name: "gzip",    srcs: gzip_srcs,    shared_libs: ["libz"],    stl: "none",}

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

3、注释

注释方式,与Golang类似。 支持行注释//与块注释/* block */

4、操作符

除了赋值的 = 以外,只有 +

5、类型

变量和属性是强类型的,变量动态地基于首次赋值,属性静态地由模块类型。支持的类型是:

  • Bool (true or false)
  • Integers (int)
  • Strings ("string")
  • Lists of strings (["string1", "string2"])
  • Maps ({key1: "value1", key2: ["value2"]})

Map可以是任何类型的值,包括嵌套Map。List和Map在最后一个值后可能有逗号。

6、默认模块

默认模块可用于在多个模块中重复相同的属性。例如:

cc_defaults {    name: "gzip_defaults",    shared_libs: ["libz"],    stl: "none",}cc_binary {    name: "gzip",    defaults: ["gzip_defaults"],    srcs: ["src/test/minigzip.c"],}

 

常用工具:

一个是格式化工具bpfmt。 与gofmt类似,可以格式化Blueprint文件。 (其实,代码基本上都是从gofmt复制而来。)

例如,格式化当前目录及其递归子目录下的所有Android.bp:

bpfmt -w .

另一个是androidmk,负责转换Android.mk为Android.bp。 其实,现阶段没有必要学会写Android.bp,通过写Android.mk来转换也行。

androidmk Android.mk > Android.bp

 

Android.mk 和Android.bp 的区别:

  • Android.mk 是Makefile的一种形式,同样采用的是DSL,包括不同的规则、条件、分支、循环等复杂的控制等等。详细看另一篇《Makefile (一)之 简介》
  • Android.bp 是在android 7.0之后使用,是一种简单的配置文件,并不像makefile 有条件、分支、循环等控制,也没有运算、逻辑等操作
  • Android.mk 文件通常具有多个具有相同名称的模块(如:库的静态和共享版本,或主机和设备版本)
  • Android.bp文件需要每个模块有唯一的名称,但是可以在多个变体中构建单个模块,如通过添加host_supported: true。androidmk转换器会生成多个冲突的模块,必须通过处理单个模块的target: { android: { }, host: { } }块里的差异来手动解决

 

单独编译Blueprint:

启用Soong以后,在Android编译最开始的准备阶段,会执行build/soong/soong.bash进行环境准备。 其中会先编译、安装Blueprint到out目录下。 也就是说,在编译Android项目时,Android.bp相关工具链会自动编译,无需费神。

Soong是与Android强关联的一个项目,而Blueprint则相对比较独立,可以单独编译、使用。

编译Blueprint,首先要具备Golang环境。 然后,按照以下步骤执行命令。

go get github.com/google/blueprintcd $GOPATH/src/github.com/google/blueprint./bootstrap.bash./blueprint.bashls bin

在新生成的bin目录中,包含4个可执行文件:

  • bpfmt
  • bpmodify
  • microfactory
  • minibp

 

工具链关系:

Android.mk、Android.bp、Soong、Blueprint、Ninja,它们之间到底有什么关系? 以下用简单的方式表达这几个概念之间的作用关系。

Android.bp --> Blueprint --> Soong --> NinjaMakefile or Android.mk --> kati --> Ninja(Android.mk --> Soong --> Blueprint --> Android.bp)

Blueprint是生成、解析Android.bp的工具,是Soong的一部分。 Soong则是专为Android编译而设计的工具,Blueprint只是解析文件的形式,而Soong则解释内容的含义。

Android.mk可以通过Soong提供的androidmk转换成Android.bp,但仅限简单配置。 目前Oreo的编译流程中,仍然是使用kati来做的转换。

现存的Android.mk、既有的Android.bp,都会分别被转换成Ninja。 从Android.mk与其它Makefile,会生成out/build-.ninja文件。 而从Android.bp,则会生成out/soong/build.ninja。 此外,还会生成一个较小的out/combined-.ninja文件,负责把二者组合起来,作为执行入口。

最终,Ninja文件才是真正直接控制源码编译的工具。

 

Android.mk 转Android.bp 实例:

下面,以一个AOSP上的简单模块,system/core/sdcard/Android.mk,来做为案例。

    LOCAL_PATH := $(call my-dir)    include $(CLEAR_VARS)    LOCAL_SRC_FILES := sdcard.cpp fuse.cpp    LOCAL_MODULE := sdcard    LOCAL_CFLAGS := -Wall -Wno-unused-parameter -Werror    LOCAL_SHARED_LIBRARIES := libbase libcutils libminijail libpackagelistparser    LOCAL_SANITIZE := integer    include $(BUILD_EXECUTABLE)

这是一个编译二进制可执行文件的小模块,内容非常简单。 通过执行androidmk Android.mk > Android.bp,可以转换成Android.bp。

    cc_binary {        srcs: [            "sdcard.cpp",            "fuse.cpp",        ],        name: "sdcard",        cflags: [            "-Wall",            "-Wno-unused-parameter",            "-Werror",        ],        shared_libs: [            "libbase",            "libcutils",            "libminijail",            "libpackagelistparser",        ],        sanitize: {            misc_undefined: ["integer"],        },    }

可以看出,虽然行数变多,但其实含义更明确了。 这个名为sdcard的模块,源码有两个cpp文件,依赖库有四个。 cc_binary,就相当于include $(BUILD_EXECUTABLE)。 转换前后,该有的信息都在,只是表达方式变化了而已。

注意如果Android.mk中包含复杂的逻辑,则转换结果会有问题,详见结果文件中的注释。目前来看,Android.mk 中一些变量,bp 还没有对应起来,例如:

// ANDROIDMK TRANSLATION ERROR: unsupported assignment to LOCAL_STATIC_ANDROID_LIBRARIES// LOCAL_STATIC_ANDROID_LIBRARIES := android-support-v4      android-support-v13      android-support-v7-preference      android-support-v14-preference// ANDROIDMK TRANSLATION ERROR: unsupported assignment to LOCAL_PROGUARD_ENABLED// LOCAL_PROGUARD_ENABLED := disabled

至于Android.bp支持多少像cc_binarycc_library这样的模块,每个模块又支持多少像namecflags这样的属性, 则只能去查找Soong的文档。

 

 

参考:

http://note.qidong.name/2017/08/android-blueprint/

 

相关文章:

Android中Kati简介

Android 中Ninja 简介

理解 Android Build 系统

更多相关文章

  1. 一款常用的 Squid 日志分析工具
  2. GitHub 标星 8K+!一款开源替代 ls 的工具你值得拥有!
  3. RHEL 6 下 DHCP+TFTP+FTP+PXE+Kickstart 实现无人值守安装
  4. Linux 环境下实战 Rsync 备份工具及配置 rsync+inotify 实时同步
  5. Android(安卓)Studio安装过程及常见问题
  6. 【Android(安卓)Studio安装部署系列】十七、Android(安卓)studio
  7. 如何启动Android虚拟机中的命令行窗口(adb)?
  8. android studio 中使用aidl
  9. android 开机启动加速

随机推荐

  1. .NET是什么
  2. 如何在Linux上安装Ruby
  3. 源代码是什么
  4. C#和C ++的区别是什么
  5. 浅谈Ruby和C语言之间的异同点
  6. C#中的数据类型是什么?C#中的四种数据类型
  7. erp系统是什么
  8. Ruby是什么?Ruby的优缺点
  9. 什么是C#中的多态性?
  10. auto是什么意思