Android重修之路:Android.bp入门浅析

238 阅读4分钟

背景

随着项目规模扩大,Makefile的复杂性和编译效率问题越来越明显,比如依赖管理混乱、并行编译效率低等。所以Google从Android7.0开始,引入Soong来对AOSP进行构建编译,而Android.bp作为Soong的配置文件,采用声明式语法,极大简化了构建逻辑。

  • Android7.0 引入ninja和kati
  • Android8.0使用Android.bp替换Android.mk,正式引入soong

构建系统使用Kati将Android.mk转换为ninja格式的文件,然后也通过Blueprint+ Soong将Android.bp转换为ninja格式的文件,通过androidmk将Android.mk转换成Andorid.bp。

工具介绍

Ninja

ninja是一个高效的编译框架,处理并行任务更好,一般针对nanja文件的修改是通过修改Android.bp文件来转换修改的,所以我们在实际的过程中只需要关注Android.bp即可。

Android.bp

它的推出完全可以立即成为了替换Android.mk,它最为Soong的配置文件,可以简化配置构建逻辑,因为它不存在分支、循环等流程控制语法,不需要做过多的逻辑理解和编写。

Soong

Soong可以理解为类似Makfefile一样的系统编译核心,提供Android.bp的语法解释,转换生成Ninja文件用于支持编译。 Kati kati的核心功能是将传统的Mmakefile转换为niaja构建文件,作为默认构建工具链的一部分,与mm/mmm等命令集成,支持模块快速编译。

Blueprint

Blueprint是生成、解析Android.bp的工具,属于Soong的一部分。

Android.bp语法

Android.bp语法主要包括以下几部分:

  • 模块
  • 变量
  • 注释
  • 运算符
  • 条件语句

模块

Android.bp可以支持的模块有很多,比如android_app、cc_binary、cc_binary_host、java_library等等,具体的可以参考build/soong/androidmk/cmd/androidmk/android.go文件中moduleTypes的定义。

image.png

示例:

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

变量

编译文件中也是可以声明一些变量的,不过他的作用域在声明它们的文件的其余部分,以及所有子 Blueprint 文件。变量一般不可变,如果要调整可以使用+=去累加赋值,或者附加到别处,需要注意和其他编程语言一样,一定要在使用前进行操作,否则无效。

支持类型:

  • 布尔(Bool)
  • 整型(Int)
  • 字符串(String)
  • 列表(List)
  • 映射(Map)
  • 结构体(Struct)

示例:

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

注释

Android.bp 文件可以包含 C 样式的多行 /* */ 注释以及 C++ 样式的单行 // 注释。

运算符

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

条件语句

Soong 不支持 Android.bp 文件中的条件语句。但是,编译规则中需要条件语句的复杂问题将在 Go中处理。大多数条件语句都会转换为映射属性,其中选择了映射中的某个值并将其附加到顶级属性。 例如,要支持特定于架构的文件,请使用以下命令:

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

编译APK示例

android_app {
    // 模块名称
    name: "MyApp",

    // 源代码目录(根据实际情况修改)
    srcs: ["src/**/*.java"],
    
    // 资源文件目录
    resource_dirs: ["res"],
    
    // 清单文件路径
    manifest: "AndroidManifest.xml",
    
    // 使用AndroidX库需要添加
    static_libs: [
        "androidx.appcompat_appcompat",
        "com.google.android.material_material",
        "androidx-constraintlayout_constraintlayout",
    ],
    
    // 平台签名(使用系统级签名时可启用)
    // privileged: true,
    
    // 使用平台签名(系统应用)
    // certificate: "platform",
    
    // 使用testkey签名(普通应用)
    certificate: "PRESIGNED",
    
    // 优化选项(启用代码混淆)
    optimize: {
        enabled: true,
        // 混淆配置
        proguard_flags_files: ["proguard.flags"],
    },
    
    // 最低SDK版本
    sdk_version: "current",
    min_sdk_version: "21",
    target_sdk_version: "34",
    
    // 包含JNI库时的配置(如果有本地代码)
    // jni_libs: ["mynative"],
}

// 如果需要预构建依赖(例如aar文件)
/*
android_library_import {
    name: "mylibrary",
    aars: ["libs/mylibrary.aar"],
    static_libs: ["androidx.appcompat_appcompat"],
}
*/

至此Android.bp的基础介绍就差不多了,更多的还是要看实际的运用,一般来讲在实际研发过程中,要配置的往往不太多,或者都是逐步增配的,所以复杂度整体来讲真的不高。

愿大家的程序永无bug~

愿大家的程序永无bug~

愿大家的程序永无bug~