Android编译系统-Android.bp

Soong是替换android中基于make的构建系统,用Android.bp文件替换Android.mk文件,并使用类似于JSON的格式来描述一个模块的构建。

Android.bp文件格式

Android.bp文件设计的非常简单,没有条件判断或者控制流语句,在Go中编写的构建逻辑中处理任何复杂情况。Android.bp文件的语法和语义可能与Bazel BUILD文件类似。

模块

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

变量

Android.bp文件可能包含顶级变量并赋值。

gzip_srcs = ["src/test/minigzip.c"],

cc_binary {
    name: "gzip",
    srcs: gzip_srcs,
    shared_libs: ["libz"],
    stl: "none",
}

变量的范围被限定为它们声明的文件的剩余部分,以及任何子 blueprint 文件。一个例外是变量不可变,能够被 += 进行附加赋值,而且只能在被引用之前。

注释

Android.bp文件能包含C风格的多行/* */注释和C++风格的单行注释//

类型

变量和属性是强类型的,基于第一个赋值动态变量,以及模块类型静态属性。他们支持的类型有:

Map 可以包含任意类型的值,包括嵌套的maps。列表和 maps 允许在最后一个值之后有逗号。

操作符

字符串、字符串列表、和maps能使用+操作符进行附加。整型可以用+操作符来总结。 附加的maps将生成两个map中键的并集,并附加的两个map中存在任何键的值。

缺省模块

缺省模块可用于在多个模块中重复相同的属性,例如:

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

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

名称解析

Soong为不同目录中的模块提供了指定相同名称的能力。只要每个模块在一个单独的名称空间中声明。 命名空间可以这样声明:

soong_namespace {
    imports: ["path/to/otherNamespace1", "path/to/otherNamespace2"],
}

每个Soong模块都会根据其在树中的位置分配一个名称空间,除非找不到soong_namespace模块,否则每个Soong模块都被认为位于当前目录或最接近的父目录中的Android.bp中的soong_namespace所定义的名称空间中。在这种情况下,该模块被认为处于隐式根目录命名空间。

当Soong试图解决声明在我的模块M中命名空间N的依赖关系D时,它导入命名空间I1,I2,I3 ...,那么如果D是形式为“// namespace:module”的完全限定名称,那么只会在指定的名称空间中搜索指定的模块名称。否则,Soong将首先查找声明在名字控制N中的模块名D。如果这个模块不存在,Soong将在名字空间l1,l2,l3...中查找模块名D,最后,Soong将在根名字空间中查找。

在我们完全转换成Make到Soong之前,Make产品配置需要指定一个值PRODUCT_SOONG_NAMESPACES。它的值应该是空格分隔的命名空间列表,用m命令把Soong导出到Make编译。在Make to Soong完全转换之后,启用命名空间的细节可能会发生变化。

格式化

Soong 包含了一个 blueprint 文件的格式化器,类似于 gofmt。使用以下命令来递归格式化当前目录中的所有 Android.bp 文件:

bpfmt -w .

标准格式包括 4 个空格的缩进,包含多个元素的列表中,每个元素之后的换行符,并且始终包括列表和 maps中的逗号。

转换Android.mk文件

Soong包括一个工具执行第一过程转换Android.mk文件到Android.bp文件:

androidmk Android.mk > Android.bp

该工具可以转换变量,模块,注释和一些条件,但任何自定义的 Makefile 规则,复杂条件或额外的 include 必须手动转换。

Android.mk和Android.bp之间的差异

编译逻辑

编译逻辑是用Go语音的blueprint框架写的。编译逻辑接收模块定义,并利用反射和编译规则解析为Go数据结构。构建规则由blueprint收集并写入ninja构建文件。

FAQ

如何写一个条件?

Soong故意不支持Android.bp文件中的条件。作为替换,需要条件的复杂的构建规则已被Go语言处理。可以使用高级语言特征来跟踪由条件引入的隐式依赖关系。大多数条件将被转换为map属性,map中的一个值将被选中并附加到顶级属性。

例如,支持特定架构的文件:

cc_library {
    ...
    srcs: ["generic.cpp"],
    arch: {
        arm: {
            srcs: ["arm.cpp"],
        },
        x86: {
            srcs: ["x86.cpp"],
        },
    },
}

有关产品变量或环境变量的更复杂条件的示例,请参阅art/build/art.go或者external/llvm/soong/llvm.go