Android 11 编译系统

Android.mk vs Android.bp

Posted by LXG on October 19, 2020

编译 Android-AOSP

Android Ninja实践

Android 编译系统


android/build$ tree -L 1
.
├── blueprint
├── buildspec.mk.default -> make/buildspec.mk.default
├── CleanSpec.mk -> make/CleanSpec.mk
├── core -> make/core
├── envsetup.sh -> make/envsetup.sh
├── make
├── soong
├── target -> make/target
└── tools -> make/tools

android_build_system

Soong 构建系统

在 Android 7.0 发布之前,Android 仅使用 GNU Make 描述和执行其构建规则。Make 构建系统得到了广泛的支持和使用,但在 Android 层面变得缓慢、容易出错、无法扩展且难以测试。 Soong 构建系统正好提供了 Android build 所需的灵活性。

Soong 构建系统是在 Android 7.0 (Nougat) 中引入的,旨在取代 Make。它利用 Kati GNU Make 克隆工具和 Ninja 构建系统组件来加速 Android 的构建。

Soong类似于之前的Makefile编译系统的核心,负责提供Android.bp语义解析,并将之转换成Ninja文件

Ninja

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

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。

Make 和 Soong 比较

以下是 Make 配置与 Soong 在 Soong 配置(Blueprint 或 .bp)文件中完成相同操作的比较。

Android.mk



LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := libxmlrpc++
LOCAL_MODULE_HOST_OS := linux

LOCAL_RTTI_FLAG := -frtti
LOCAL_CPPFLAGS := -Wall -Werror -fexceptions
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/src

LOCAL_SRC_FILES := $(call \
     all-cpp-files-under,src)
include $(BUILD_SHARED_LIBRARY)

Android.bp


cc_library_shared {
     name: “libxmlrpc++”,

     rtti: true,
     cppflags: [
           “-Wall”,
           “-Werror”,
           “-fexceptions”,
     ],
     export_include_dirs: [“src”],
     srcs: [“src/**/*.cpp”],

     target: {
           darwin: {
                enabled: false,
           },
     },
}

Android.bp 文件格式

根据设计,Android.bp 文件很简单。它们不包含任何条件语句,也不包含控制流语句;所有复杂问题都由用 Go 编写的构建逻辑处理。Android.bp 文件的语法和语义都尽可能与 Bazel BUILD 文件类似。

模块


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

类型

布尔值(true 或 false) 整数 (int) 字符串 (“string”) 字符串列表 ([“string1”, “string2”]) 映射 ({key1: “value1”, key2: [“value2”]})

Glob

接受文件列表的属性(例如 srcs)也可以采用 glob 模式。glob 模式可以包含普通的 UNIX 通配符 ,例如 *.java。glob 模式还可以包含单个 ** 通配符作为路径元素,与零个或多个路径元素匹配。例如,java/**/.java 同时匹配 java/Main.java 和 java/com/android/Main.java 模式。

变量

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++ 样式的单行 // 注释。

运算符

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

条件语句

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

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


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

格式设置工具

Soong 包含一个针对 Blueprint 文件的规范格式设置工具,类似于 gofmt。如需以递归方式重新设置当前目录中所有 Android.bp 文件的格式,请运行以下命令:

bpfmt -w .

规范格式包括缩进四个空格、多元素列表的每个元素后面有换行符,以及列表和映射末尾有英文逗号。

Demo

SettingsLib


android_library {

    name: "SettingsLib",

    defaults: [
        "SettingsLibDependenciesWithoutWifiTracker",
        "framework-wifi-vendor-hide-access-defaults",
    ],

    // TODO(b/149540986): revert this change.
    static_libs: [
         // All other dependent components should be put in
         // "SettingsLibDependenciesWithoutWifiTracker".
        "WifiTrackerLib",
    ],

    // ANDROIDMK TRANSLATION ERROR: unsupported assignment to LOCAL_SHARED_JAVA_LIBRARIES
    // LOCAL_SHARED_JAVA_LIBRARIES := androidx.lifecycle_lifecycle-common

    resource_dirs: ["res"],

    srcs: ["src/**/*.java", "src/**/*.kt"],

    min_sdk_version: "21",

}

java_defaults {
    name: "SettingsLibDependenciesWithoutWifiTracker",
    static_libs: [
        "androidx.annotation_annotation",
        "androidx.legacy_legacy-support-v4",
        "androidx.recyclerview_recyclerview",
        "androidx.preference_preference",
        "androidx.appcompat_appcompat",
        "androidx.lifecycle_lifecycle-runtime",
        "androidx.mediarouter_mediarouter-nodeps",
        "iconloader",

        "SettingsLibHelpUtils",
        "SettingsLibRestrictedLockUtils",
        "SettingsLibActionBarShadow",
        "SettingsLibAppPreference",
        "SettingsLibSearchWidget",
        "SettingsLibSettingsSpinner",
        "SettingsLibLayoutPreference",
        "SettingsLibActionButtonsPreference",
        "SettingsLibEntityHeaderWidgets",
        "SettingsLibBarChartPreference",
        "SettingsLibProgressBar",
        "SettingsLibAdaptiveIcon",
        "SettingsLibRadioButtonPreference",
        "SettingsLibDisplayDensityUtils",
        "SettingsLibUtils",
    ],
}

// NOTE: Keep this module in sync with ./common.mk
java_defaults {
    name: "SettingsLibDefaults",
    static_libs: [
        "androidx.annotation_annotation",
        "androidx.lifecycle_lifecycle-common",
        "androidx.legacy_legacy-support-v4",
        "androidx.lifecycle_lifecycle-runtime",
        "androidx.recyclerview_recyclerview",
        "androidx.preference_preference",
        "androidx.appcompat_appcompat",
        "androidx.legacy_legacy-preference-v14",
        "SettingsLib",
    ],
}

Settings


java_library {
    name: "settings-logtags",
    srcs: ["src/**/*.logtags"],
}

genrule {
    name: "statslog-settings-java-gen",
    tools: ["stats-log-api-gen"],
    cmd: "$(location stats-log-api-gen) --java $(out) --module settings"
        + " --javaPackage com.android.settings.core.instrumentation --javaClass SettingsStatsLog",
    out: ["com/android/settings/core/instrumentation/SettingsStatsLog.java"],
}

java_library {
    name: "statslog-settings",
    srcs: [
        ":statslog-settings-java-gen",
    ],
}

// Build the Settings APK
android_library {
    name: "Settings-core",
    platform_apis: true,
    defaults: [
        "SettingsLibDefaults",
        "SettingsLib-search-defaults",
        "framework-wifi-vendor-hide-access-defaults",
    ],

    srcs: ["src/**/*.java"],

    static_libs: [
        "androidx-constraintlayout_constraintlayout",
        "androidx.slice_slice-builders",
        "androidx.slice_slice-core",
        "androidx.slice_slice-view",
        "androidx.core_core",
        "androidx.appcompat_appcompat",
        "androidx.cardview_cardview",
        "androidx.preference_preference",
        "androidx.recyclerview_recyclerview",
        "com.google.android.material_material",
        "setupcompat",
        "setupdesign",
        "androidx-constraintlayout_constraintlayout-solver",
        "androidx.lifecycle_lifecycle-runtime",
        "androidx.lifecycle_lifecycle-extensions",
        "guava",
        "jsr305",
        "settings-contextual-card-protos-lite",
        "settings-log-bridge-protos-lite",
        "contextualcards",
        "settings-logtags",
        "statslog-settings",
        "zxing-core-1.7",
        "android.hardware.dumpstate-V1.0-java",
        "android.hardware.dumpstate-V1.1-java",
    ],

    libs: [
        "telephony-common",
        "ims-common",
        "app-compat-annotations",
        "telephony-ext",
    ],
}

platform_compat_config {
    name: "settings-platform-compat-config",
    src: ":Settings-core",
    system_ext_specific: true,
}

android_app {
    name: "Settings",
    platform_apis: true,
    certificate: "platform",
    system_ext_specific: true,
    privileged: true,
    required: [
        "privapp_whitelist_com.android.settings",
        "settings-platform-compat-config",
    ],
    static_libs: ["Settings-core"],
    resource_dirs: [],
    optimize: {
        proguard_flags_files: ["proguard.flags"],
    },
}

android_library_import {
    name: "contextualcards",
    aars: ["libs/contextualcards.aar"],
}

nijia 编译很慢问题

使用ninja命令提高单模块编译效率