• AOSP编译系统演进:从Make到Ninja的技术升级(Android13)


    AOSP编译系统演进:从Make到Ninja的技术升级(Android13)

    引言

    在Android 7.0之前,Android的编译系统主要使用GNU Make和Android.mk进行构建规则的描述和执行。然而,随着项目规模的扩大,Makefile组织方式导致了编译时间的增长等问题。

    为了解决这些问题,从Android 7.0开始,Google引入了Soong构建系统,Soong 构建系统正好提供了 Android build 所需的灵活性

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

    ninja作为替代GNU Make的工具,并引入了kati工具来将Android.mk转换为ninja构建规则文件。随后,在Android 8.0中,Google进一步引入了Android.bp文件,用作替代Android.mk的纯配置文件。

    Android.bp文件本质上是一个基于json格式的配置文件,不包含控制流程等复杂语法。它通过Blueprint+soong的转换过程生成相应的ninja构建规则文件(build.ninja),然后使用ninja进行实际的构建工作。

    通过这一系列改进,Google的目标是加速Android项目的构建过程,提高整体效率。Soong构建系统由Kati GNU Make克隆工具和Ninja构建系统组件组成,这进一步优化了Android项目的构建流程。

    注意,最新消息, Google计划未来几年将AOSP编译系统全面向bazel迁移,此迁移目前处于早期阶段,但您可以对当前的 build 文件做出一些更改,以便开始针对 Bazel 做好准备。迁移完成后,Bazel 将取代 AOSP 中的所有现有构建系统和 build 配置系统(Make、Kati、Soong、基于 Make 的产品配置)。

    https://source.android.google.cn/docs/setup/build/bazel/introduction?hl=zh-cn

    构建流程

    编译系统构成

    Android的编译目录位于/build中。在Android 13源码中的build目录中,有几个重要的文件夹:

    1. blueprint:用于处理Android.bp文件,生成*.ninja文件,以供ninja处理。
    2. kati:用于处理Android.mk文件,生成*.ninja文件,同样供ninja处理。
    3. make:该文件夹包含原始的make流程,例如envsetup.sh等。
    4. soong:构建系统的核心部分,其中包括soong_ui.bash。

    在build目录中,core文件夹被链接到make/core,而envsetup.sh被链接到make/envsetup.sh。这样做主要是为了对使用者屏蔽切换编译系统时的差异。

    总结起来,build目录中的blueprint和kati文件夹用于处理Android.bp和Android.mk文件,生成相应的*.ninja文件供ninja处理,而make文件夹仍然保留了原始的make流程,而soong文件夹则是构建系统的核心部分。

    编译流程

    下图展示了soong的编译流程

    在Android的编译过程中,Android.bp文件会被收集到out/soong/build.ninja.d目录。基于这些信息,blueprint工具会生成out/soong/build.ninja文件。

    另一方面,Android.mk文件会由kati和ckati工具生成out/build-aosp_arm.ninja文件。

    最后,这两个ninja文件会被整合合并到out/combined-aosp_arm.ninja文件中。这个合并后的ninja文件包含了Android的完整编译规则,并用于执行实际的构建操作。

    编译步骤

    source build/envsetup.sh
    lunch aosp_arm-eng # 不清楚想要lunch的项目时,可以先执行lunch,然后在选择项目
    make -j8   
    
    • 1
    • 2
    • 3

    编译初始化

    envsetup.sh说明

    编译的第一步是执行下面命令:

    source build/envsetup.sh
    
    • 1

    下面是它做的一些事情

    lunch说明

    环境初始化完毕,我们需要启动一个编译目标,比如我们想要编译aosp_arm-eng, 那么我们只需要执行下面命令:

    lunch 3
    #或者
    lunch aosp_arm-eng
    
    • 1
    • 2
    • 3

    如果你不知道想要编译的目标是什么,直接执行一个lunch命令,会列出所有的目标,直接回车,会默认使用aosp_arm-eng这个目标。

    soong编译过程


    当执行runKatiBuild时,有一个重要的步骤是加载build/make/core/main.mk文件。这个main.mk文件是Android Build系统的主控文件。从main.mk开始,它使用include命令将所有需要的.mk文件包含进来,最终在内存中形成一个包含所有编译脚本的集合,相当于一个巨大的Makefile文件。这个Makefile文件看起来可能很庞大,但实际上主要由三种内容构成:变量定义、函数定义和目标依赖规则。此外,mk文件之间的相互包含也非常重要。

    Make 和 Soong 比较

    Make示例

    ##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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    Soong示例

    ##Android.bp
    cc_library_shared {
         name: “libxmlrpc++”,
    
         rtti: true,
         cppflags: [
               “-Wall”,
               “-Werror”,
               “-fexceptions”,
         ],
         export_include_dirs: [“src”],
         srcs: [“src/**/*.cpp”],
    
         target: {
               darwin: {
                    enabled: false,
               },
         },
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    工具链关系

    Android.mk文件、Android.bp、kati、Soong、Blueprint和Ninja之间的关系如下:

    1. Android.bp --> Blueprint --> Soong --> Ninja

      • Android.bp文件通过Blueprint工具进行生成和解析,然后传递给Soong工具进行处理,最终生成Ninja文件。
    2. Makefile或Android.mk --> kati --> Ninja

      • Makefile或Android.mk文件经过kati工具的转换,生成Ninja文件。
    3. Android.mk --> Soong --> Blueprint --> Android.bp

      • Android.mk文件可以通过Soong提供的androidmk工具转换为Android.bp文件,但仅适用于简单的配置。

    在编译过程中,现有的Android.mk文件和已有的Android.bp文件分别被转换为相应的Ninja文件。从Android.mk及其他Makefile文件生成的是out/build-.ninja文件,而从Android.bp文件生成的是out/soong/build.ninja文件。此外,还会生成一个较小的out/combined-.ninja文件,用于将两者组合起来作为执行入口。

    最终,Ninja文件是直接控制源码编译的工具。它们包含了编译所需的规则和指令,用于构建Android系统。

    Soong模块编译小技巧

    我们一般使用mm命令进行模块编译,但是每次修改都使用mm,那么编译时间会让你怀疑人生,因为每次执行mm都会做全局检查,重新生成*.ninja全局文件,这个速度是很慢的,所以建议如下
    Android.bp或者Android.mk有改动, 或者源码文件有增删的情况下,使用mm命令。

    无Android.bp或者文件增删情况下使用ninja命令,使用脚本封装一些快捷命令,这样就能跳过全局检查,节省编译时间。

    参考链接

    [Soong构建系统] https://android.googlesource.com/platform/build/soong/+/refs/heads/master/README.md
    [Android Make构建系统] https://android.googlesource.com/platform/build/+/master/README.md
    [借助 Bazel 打造 Android 平台]https://docs.bazel.build/versions/master/bazel-overview.html?hl=zh-cn

  • 相关阅读:
    基于webapi的websocket聊天室(番外一)
    Kotlin(十六) 函数式编程
    深入剖析Tomcat之ERR_INVALID_HTTP_RESPONSE
    Web应用开发介绍
    java项目之书店仓库管理系统(ssm源码+文档)
    java Spring Boot RequestHeader设置请求头,当请求头中没有Authorization 直接400问题解决
    【论文翻译】关于在并行快照隔离中读取更新鲜的快照
    文件解析工具
    docker文件过大,Docker容器引擎,迁移/var/lib/docker/到本机其它挂载分区或远程主机的某个分区。docker迁移
    C#获取http请求的JSON数据并解析
  • 原文地址:https://blog.csdn.net/u011897062/article/details/134465719