当前位置: 首页 > news >正文

【Android构建系统】了解Soong构建系统

背景介绍

在Android7.0之前,Android使用GNU Make描述和执行build规则。Android7.0引入了Soong构建系统,弥补Make构建系统在Android层面变慢、容易出错、无法扩展且难以测试等缺点。

Soong利用Kati GNU Make克隆工具和Ninja构建系统组件来加速Android的构建。

下面从两个方面来了解Soong构建系统:

  • 使用Soong构建系统构建自己模块要熟悉的两个内容,即.bp和.go。
  • Soong构建系统和Make构建系统的差异。

1.Soong构建系统中.bp和.go的关系

在Android的Soong构建系统中,.bp (Blueprint)文件和.go(Golang)文件共同协作,关系大概如下:

1. .bp文件,声明式构建配置

.bp文件用于定义模块及其属性,采用类似JSON的声明式语法,描述模块的构建规则(如源文件、依赖项、编译选项等)

.bp文件不支持条件语句或控制流,仅用于静态配置。

Soong预定义了模块类型,如cc_library,cc_binary,  java_library等。

 例如,Android15源码中Camera HAL AIDL Demo中的一段:

//hardware/google/camera/common/hal/aidl_service/Android.bp
cc_binary {name: "android.hardware.camera.provider@2.7-service-google",defaults: ["hardware_camera_service_defaults","camera_service_eager_hal_defaults",],init_rc: ["android.hardware.camera.provider@2.7-service-google.rc],
}

2. .go文件,逻辑处理与扩展

.go文件用于实现复杂的构建逻辑,例如

  • 解析.bp文件并生成Ninja构建规则
  • 处理条件编译、环境变量、动态依赖等无法在.bp中直接表达的逻辑
  • 扩展模块类型或自定义构建行为(如通过Go的发射机制)

使用GO语言编写,灵活性高,可调用Android构建系统的底层API。

例如,通过LoadHook动态修改模块属性:

func myHook(ctx android.LoadHookContext) {if ctx.AConfig().IsEnvTrue("USE_FEATURE_X") {ctx.AppendProperties(map[string]interface{}{"cflags": ["-DFEATURE_X"]})}
}

3.协作关系

.bp负责“做什么”(声明模块和属性), .go负责“怎么做”(实现复杂逻辑和生成构建规则)

转换流程:

  1. Soong解析所有.bp文件,生成模块依赖图。
  2. .go代码处理模块间的动态逻辑(如根据产品配置选择源码)。
  3. 最终转换为Ninja可执行的构建规则。

4.协作的典型例子1-条件编译

在.bp中通过arch或target(.go中预定义的变量)分平台配置,而跨模块的全局条件(如产品型号)需要在.go中实现。

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

 如果arch是arm, srcs是arm.cpp。arch是soong中预定义的变量,用于分平台构建。

5.协作的典型例子2-模块级别控制

例如, Android15 Camera HAL AIDL Demo构建中的一段:

gch_lazy_hal_cc_defaults {name: "camera_service_eager_hal_defaults",enabled: true,soong_config_variables: {use_lazy_hal: {enabled: false,},},
}gch_lazy_hal_cc_defaults {name: "camera_service_lazy_hal_defaults",enabled: false,soong_config_variables: {use_lazy_hal: {enabled: true,},},
}

6.总结

.bp文件.go文件
语法声明式,类JSON命令式,Go语言
灵活性有限,无逻辑控制高,可编程
适用场景模块定义、静态依赖动态逻辑、构建规则扩展
维护者开发者构建系统工程师/高级开发者

2.Soong构建系统和Make构建系统的差异

这两种构建系统在设计理念、语法结构和执行效率等方面又着显著的差异。以下从多个维度对这两种构建系统进行对比分析。

基本概念与发展背景

Make构建系统

  • Android早期使用的构建系统,基于GNU Make实现
  • 通过Android.mk文件定义构建规则
  • 随着Android项目复杂度增加,逐渐暴露出性能瓶颈和可维护性问题

Soong构建系统

  • Android 7.0(Nougat)引入的新构建系统,旨在取代Make
  • 使用Android.bp文件(Blueprint格式)定义构建规则
  • 采用Go语言编写,与Kati和Ninja构建系统组件配合使用
  • 设计目标式解决Make系统在大型项目中的性能瓶颈

语法结构与配置方式

Make语法特点

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libexample
LOCAL_SRC_FILES := example.cpp
include $(BUILD_SHARED_LIBRARY)
  • 命令式语法,包含变量定义和流程控制
  • 需要手动管理依赖关系
  • 基于shell命令执行构建任务

Soong语法特点

cc_library_shared {name: "libexample",srcs: ["example.cpp"],
}
  • 声明式语法,类似JSON格式
  • 不支持条件语句和控制流,复杂逻辑由Go代码处理
  • 强类型变量和属性系统
  • 更简洁直观的模块定义方式

系统架构与工作原理

Make系统架构

  • 串行构建方式,依赖关系手动指定
  • 扩展性差,配置复杂度随项目规模增长而急剧上升
  • 增量构建能力有限

Soong系统架构

  •  自动分析模块依赖关系并生成构建图
  • 支持并行构建,充分利用多核CPU
  • 高效的增量构建机制,仅重新编译变更部分
  • 模块化设计,易于扩展

性能与效率对比

构建速度

  • Make系统在大型项目上构建速度较慢,特别是全量构建时
  • Soong通过并行构建和精确的依赖分析,显著提升构建速度

资源利用率

  • Make系统资源利用率低,主要受限于串行执行
  • Soong能充分利用现代多核处理器,实现高效资源利用

增量构建

  • Make需要开发者手动维护依赖关系,增量构建不可靠
  • Soong自动跟踪文件变更,增量构建精确高效

功能特性对比

特性Make构建系统Soong构建系统
语法类型命令式声明式
依赖管理手动指定自动处理
并行构建有限支持原生支持
增量构建基本支持高效支持
扩展性有限高度可扩展
跨平台需要适配原生支持
学习曲线相对简单较陡峭
条件编译支持通过Go代码实现
模块化有限高度模块化
与Android集成逐渐淘汰深度集成

实际应用场景

适合使用Make的场景

  • 维护旧的Android项目代码
  • 小型项目或原型开发
  • 需要与现有Make系统集成的场景

适合使用Soong的场景

  • 新的Android平台开发
  • 大型复杂项目
  • 需要高效并行构建的环境
  • 需要精确增量构建的项目

迁移于兼容性

  • Soong设计时考虑了与Make系统的兼容性
  • 提供androidmk工具可将Android.mk转换为Android.bp
  • 过渡期间采用混合模式:Make由Kati解析生成ninja文件,再与Soong的ninja文件合并
  • 完全迁移到Soong是Android构建系统的未来方向

Make构建系统作为Android早期的构建解决方案,已经逐渐无法满足现代大型项目的需求。Soong构建系统通过声明式配置、自动依赖管理和并行构建等特性,显著提升了Android项目的构建效率和可维护性。

Make和Soong构建系统的使用建议

  1. 新项目应直接采用Soong构建系统
  2. 旧项目可逐步将Android.mk转换为Android.bp
  3. 复杂构建逻辑可通过Go扩展实现
  4. 充分利用Soong提供的工具链(bpfmt等)提高开发效率

随着Android生态的发展,Soong构建系统将持续演进,可能最终向Bazel构建系统过渡,但其核心优势仍将在Android构建领域发挥重要作用。

相关文章:

  • 算法基础 -- 小根堆构建的两种方式:上浮法与下沉法
  • 一款强大的压测带宽工具-iperf3
  • 容器编排利器-k8s入门指南
  • [AI算法] LLM训练-构建transformers custom model
  • 容器化-k8s-使用和部署
  • 前端面经 手写Promise
  • Linux 内核中 inet_accept 的实现与自定义传输协议优化
  • 部署docker上的redis,idea一直显示Failed to connect to any host resolved for DNS name
  • Tcping详细使用教程
  • .NET Core liunx二进制文件安装
  • 能源数字化转型关键引擎:Profinet转Modbus TCP网关驱动设备协同升级
  • 《k-means 散点图可视化》实验报告
  • 简单入门RabbitMQ
  • OrangePi Zero 3学习笔记(Android篇)11 - IR遥控器
  • python自学笔记2 数据类型
  • 汉诺塔超算堆栈结构编码和流程详细设计(附源代码)
  • [SpringBoot]Spring MVC(2.0)
  • Android native崩溃问题分析
  • Python基础:集合(Set)
  • 今日积累:若依框架配置QQ邮箱,来发邮件,注册账号使用
  • 体坛联播|热刺追平单赛季输球纪录,世俱杯或创收20亿美元
  • 美联储官员:美国经济增速可能放缓,现行关税政策仍将导致物价上涨
  • 张巍任中共河南省委副书记
  • 《日出》华丽的悲凉,何赛飞和赵文瑄演绎出来了
  • 自强!助残!全国200个集体和260名个人受到表彰
  • 泽连斯基已离开土耳其安卡拉