Android学习17 -- Soong编译系统

这篇文章详细介绍了在Android开发中,如何处理.go源代码文件的编译,涉及Gradle构建工具、Ahead-of-Time(AOT)编译以及D8字节码优化器的选择和使用,旨在帮助开发者理解Android编译流程的关键步骤。

这个也是3月就todo了,但是一直没更新。最开始被android的编译系统搞得头大,因为和linux上区别还是很大,后面习惯了慢慢也好了,也一直没整理,现在整理一下吧。

官方文档:

https://source.android.com/docs/setup/build?hl=zh-cn

1 整体流程

首先,还是看看整个编译的流程。

通过这个图,可以看到流程就是输入还是Android.bp,通过soong转换成build.ninja,然后装换成大的ninja文件,通过ninja编译,生成各个产物。最后进行打包。

详细流程如下:

1. 初始化和配置阶段
当运行 make 或 soong 命令时,构建系统首先会执行初始化过程。初始化过程中,Soong 会解析环境变量、平台设置、构建配置等。
构建系统会读取 Android.bp 和 soong.config 文件,设置全局构建参数。soong.config 中可能会定义一些平台特定的设置,如编译选项、目标架构等。
Blueprint 的模块配置文件 .bp 会被加载,这些文件定义了不同的模块及其构建规则。


2. Blueprint 配置解析
在初始化完成后,Soong 会开始解析所有的 .bp 文件。每个 .bp 文件定义了一个或多个模块(如 cc_binary、cc_library 等)。
Soong 会根据模块的类型解析它们的构建规则,例如哪些源文件需要编译、哪些库是依赖项、输出文件是什么等。
Soong 会自动处理模块间的依赖关系,并构建模块间的依赖图。


3. 生成 Ninja 构建文件
在解析完所有的 Blueprint 配置后,Soong 会生成一个 build.ninja 文件,这个文件包含了详细的构建指令。
build.ninja 是 Ninja 构建系统所需要的文件,它描述了如何从源文件生成目标文件(如 .o 文件、静态库、共享库、可执行文件等)。
build.ninja 文件会定义每个构建任务的输入文件、输出文件和构建命令。


4. 执行 Ninja 构建任务
Soong 会将控制权交给 Ninja,它使用 build.ninja 文件来执行构建任务。
Ninja 会并行执行构建任务,根据 build.ninja 文件中的依赖关系,决定哪些文件需要重新编译,哪些可以跳过。
Ninja 会生成最终的构建输出,如可执行文件、库文件等,保存在 out/ 目录中。


5. 增量构建
Ninja 支持增量构建,它会检测源文件是否发生变化。如果没有变化,它会跳过相应的构建任务,只重新构建被修改或依赖于修改的文件。
Soong 和 Ninja 的增量构建机制显著提高了构建效率,避免了不必要的重新编译。


6. 构建完成
一旦 Ninja 完成了所有的构建任务,最终的输出文件(如 .apk、.so、.bin 等)将位于 out/ 目录中。

7 打包
使用这些输出文件进行进一步的测试、打包或部署。

由此可以看出,soong的主要组成部分就是BP文件Blueprint,soong,ninja。

2 Blueprint

Soong是基于Blueprint语法的,也就是经常看到的那个Android.bp。之前还有Android.mk,那个更接近makefile。

这里简单列一下Blueprint的语法。感觉有点接近python。

Blueprint 是 Soong 构建系统的配置语言,用于描述 Android 项目中的模块及其构建规则。它的语法简洁、声明式,主要用于 .bp 文件中。Blueprint 语法灵感来源于 Starlark(原名 Python),但它针对构建配置进行了定制,支持模块化和依赖关系管理。

1. 基本语法结构

Blueprint 的语法主要由 模块属性赋值 组成。一个 Blueprint 文件通常包含多个模块的定义。

1.1 模块定义

模块通常通过关键字来定义,每个模块代表一个构建目标或任务。

cc_binary {
    name: "my_program",
    srcs: ["main.cpp", "utils.cpp"],
    shared_libs: ["libfoo"],
}
  • cc_binary:模块类型,表示一个 C++ 可执行文件。
  • name:模块的名称。
  • srcs:源文件列表,表示需要编译的源代码文件。
  • shared_libs:依赖的共享库列表。

1.2 属性(Attributes)

每个模块都有一组属性,这些属性用于定义模块的特性和行为。

  • name:模块的名称。
  • srcs:模块的源文件列表。
  • deps:依赖的其他模块。
  • static_libs:依赖的静态库。

2. 常见模块类型

Blueprint 支持多种模块类型,用于描述不同类型的构建目标。常见的模块类型有:

  • cc_binary:用于生成 C++ 可执行文件。
  • cc_library:用于生成 C++ 静态库或共享库。
  • java_library:用于生成 Java 库。
  • android_app:用于生成 Android 应用。
cc_binary {
    name: "my_app",
    srcs: ["main.cpp"],
    static_libs: ["libfoo"],
}

cc_library {
    name: "libfoo",
    srcs: ["foo.cpp"],
}

3. 属性赋值

Blueprint 使用 键值对 来定义属性。每个属性都由一个 键(key)值(value) 组成,值可以是单个元素、列表或其他模块。

  • 单个值
name: "my_module"
  • 列表
srcs: ["file1.cpp", "file2.cpp"]
  • 模块引用
deps: ["libfoo"]

4. 条件语句

Blueprint 也支持条件表达式,通常用来控制属性的赋值或模块的包含。

if some_condition {
    srcs: ["file1.cpp"]
} else {
    srcs: ["file2.cpp"]
}

5. 函数和方法

Blueprint 支持一些内置函数,用来处理文件路径、版本控制等操作。例如,可以使用 join() 函数将路径合并:

srcs: [join("src", "main.cpp")]

6. 模块依赖

模块之间的依赖关系在 Blueprint 中非常重要。依赖关系通过 depsshared_libs 等属性来指定。

cc_binary {
    name: "my_program",
    srcs: ["main.cpp"],
    deps: ["libfoo", "libbar"],
}

7. 嵌套模块

Blueprint 文件可以包含多个模块定义,每个模块都有独立的属性,可以通过嵌套来组织复杂的项目结构。

cc_library {
    name: "libfoo",
    srcs: ["foo.cpp"],
}

cc_binary {
    name: "my_program",
    srcs: ["main.cpp"],
    deps: ["libfoo"],
}

8. 变量和表达式

Blueprint 支持使用变量来简化模块的配置。可以在一个地方定义变量,并在多个模块中引用。

MY_SRC_FILES = ["main.cpp", "utils.cpp"]

cc_binary {
    name: "my_program",
    srcs: MY_SRC_FILES,
}

9. 列表和字典

Blueprint 中的属性值可以是列表、字典等数据结构。列表用于存储多个元素,字典则用于存储键值对。

列表:

srcs: ["file1.cpp", "file2.cpp"]

字典:

cc_binary {
    name: "my_program",
    srcs: ["main.cpp"],
    flags: {
        cppflags: ["-DDEBUG", "-O2"],
    },
}

总结

Blueprint 是一个声明式的配置语言,使用简洁的语法来定义 Android 项目中的构建模块。它通过 模块属性依赖关系 来描述构建过程,并支持条件语句、函数、变量等特性来提高灵活性和可维护性。其语法简单明了,适合用于大规模的构建系统配置。

如果你有具体的模块或语法问题,欢迎继续提问!

3 Soong

Soong 本身是一个 Go 语言程序,通过 makem 来间接调用它。可以使用 Soong 提供的一些命令行工具来单独解析 Blueprint 配置文件。

使用 soong 工具

在 Android 源码目录下,你可以使用 soong 命令直接触发 Soong 构建过程。Soong 解析 Android.bp 文件的过程是自动的,通常无需指定特定的命令来解析特定的 bp 文件,但你可以通过以下方式来手动触发它。

  1. 使用 soong 生成 Ninja 构建文件: 在源码根目录下,运行:

  2. bash

    复制代码

    make soong

    该命令会触发 Soong 解析 Android.bp 文件并生成 build.ninja 文件。soong 会扫描所有的 Android.bp 文件并生成适合 Ninja 执行的构建任务。

  3. 直接运行 Soong 来解析 Blueprint 文件: 如果你想要仅仅解析 Blueprint 配置文件并不实际执行构建任务,可以使用 soong 作为独立命令来查看或验证 Blueprint 文件的内容。通常,通过以下命令运行:

     

    bash

    复制代码

    build/soong/soong_ui --make-mode

    该命令会让 Soong 进入 make 模式,即开始解析所有 Android.bp 文件,并准备生成 build.ninja 文件。

3. 查看生成的 build.ninja 文件

Soong 会生成 build.ninja 文件,里面包含了构建过程中需要执行的具体任务。你可以在构建目录(通常是 out/ 目录)中找到这个文件:

 
 

bash

复制代码

out/soong/build.ninja

这个文件描述了如何编译和链接各个模块。

4. 调试和验证

如果你仅仅想调试 Blueprint 文件,验证 Soong 是否正确解析了你的 Android.bp 文件,可以使用 Soong 的调试工具来查看解析过程:

 
 

bash

复制代码

build/soong/soong_ui --dump-vars

该命令会打印出与构建系统相关的所有变量和设置,帮助你了解构建过程中的所有配置。

5. 单独执行构建任务

一旦你生成了 build.ninja 文件,你可以直接使用 Ninja 来执行构建任务:

 
 

bash

复制代码

ninja -C out/soong

这将根据 build.ninja 文件执行实际的编译和构建步骤。

4 Ninja

之前写过,可以直接参考Ninja小结_ninja-build-CSDN博客

参考:

Android学习13 -- 编译系统_android13编译-CSDN博客

Android 编译介绍_android.go文件选择编译-CSDN博客

https://www.jianshu.com/p/b088befb8c61

安卓编译时出现报错,报错如下,情分析原因。报错信息:[ 18% 707/3795] //prebuilts/sdk/current/support:android-support-compat-nodeps aapt2 link [common] FAILED: out/soong/.intermediates/prebuilts/sdk/current/support/android-support-compat-nodeps/android_common/package-res.apk out/soong/.intermediates/prebuilts/sdk/current/support/android-support-compat-nodeps/android_common/gen/proguard.options out/soong/.intermediates/prebuilts/sdk/current/support/android-support-compat-nodeps/android_common/gen/R.jar out/soong/.intermediates/prebuilts/sdk/current/support/android-support-compat-nodeps/android_common/R.txt out/soong/.intermediates/prebuilts/sdk/current/support/android-support-compat-nodeps/android_common/extra_packages rm -rf out/soong/.intermediates/prebuilts/sdk/current/support/android-support-compat-nodeps/android_common/gen/aapt2/R && out/soong/host/linux-x86/bin/aapt2 link -o out/soong/.intermediates/prebuilts/sdk/current/support/android-support-compat-nodeps/android_common/package-res.apk --static-lib --no-static-lib-packages --auto-add-overlay --manifest out/soong/.intermediates/prebuilts/sdk/current/support/android-support-compat-nodeps/android_common/aar/AndroidManifest.xml --auto-add-overlay -I out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/package-res.apk --java out/soong/.intermediates/prebuilts/sdk/current/support/android-support-compat-nodeps/android_common/gen/aapt2/R --proguard out/soong/.intermediates/prebuilts/sdk/current/support/android-support-compat-nodeps/android_common/gen/proguard.options --output-text-symbols out/soong/.intermediates/prebuilts/sdk/current/support/android-support-compat-nodeps/android_common/R.txt -R @out/soong/.intermediates/prebuilts/sdk/current/support/android-support-compat-nodeps/android_common/aapt2/overlay.list && out/soong/host/linux-x86/bin/soong_zip -write_if_changed -jar -o out/soong/.intermediates/prebuilts/sdk/current/support/android-support-compat-nodeps/android_common/gen/R.jar -C out/soong/.intermediates/prebuilts/sdk/current/support/android-support-compat-nodeps/android_common/gen/aapt2/R -D out/soong/.intermediates/prebuilts/sdk/current/support/android-support-compat-nodeps/android_common/gen/aapt2/R &&out/soong/host/linux-x86/bin/extract_jar_packages -i out/soong/.intermediates/prebuilts/sdk/current/support/android-support-compat-nodeps/android_common/gen/R.jar -o out/soong/.intermediates/prebuilts/sdk/current/support/android-support-compat-nodeps/android_common/extra_packages --prefix '--extra-packages ' runtime: failed to create new OS thread (have 2 already; errno=11) runtime: may need to increase max user processes (ulimit -u) fatal error: newosproc
07-19
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值