背景
有时我们需要使用同一套Android源码编译生成各种差异化产品固件,比如:A产品、B产品、C产品,各产品之间大部分功能是相同的,仅个别功能定义上有差别。
方法一 Android默认的做法是在源码 device 目录下增加A、B、C产品,差异化通过 makefile 配置区分。比如:预装哪些APK,使用哪个开机动画。但这种方法有以下几个缺点:
● 每种产品都需要单独编译整个Android源码,而Android源码编译需要耗费较长时间。
● 无法决定 kernel 的差异,比如:A、B、C产品它们的硬件上有差异,需要分别编译不同的dts文件,这种方式就无法实现。
● 如果A、B、C产品之间的差异非常小,比如仅仅是开机动画的不同,也增加一个device来区分,也需要单独编译整个Android源码,就有点太耗费资源。
方法二 通过git分支来管理,每个产品单独拉一个git分支,这种方式适应于源码差异非常大,并且无法兼容,相互之间存在冲突的情况。像上面所述,如果A、B、C产品之间仅仅是开机动画的不同,也通过单独git分支来维护,自然就不妥了。另外,一旦产品数量多起来,维护各种git分支就变的相当困难。
方法三 将Android源码与产品解耦,Android源码只负责各种基础功能,产品相关的差异配置全部提取到另外一个仓库。我们在这里暂且约定Android源码为『Android仓库』,产品配置的仓库为『产品仓库』(这里的仓库指git仓库,可以理解为存在两个git仓库,一个管理Android源码,一个管理产品配置)。
我们将『Android仓库』编译后生成的相关文件打包,将其复制到特定路径下,称之为『二次开发包』。『产品仓库』中集成了二次打包相关脚步,当需要生成特定产品固件时,将『二次开发包』复制到『产品仓库』指定路径下,脚本会解压『二次开发包』并将特定产品的所有配置合入其中,从而生产最终产品固件。
这样一来,A、B、C产品共用同一份『二次开发包』,只要Android源码没有修改,就不用重新编译Android源码,而只需要执行『产品仓库』中的二次打包脚步,这往往只需要几分钟就可以打包完成,大大提高了发布产品固件的速度。
下面用一张简单的示意图来描述整个过程:
上面示意图说明『Adroid仓库』默认支持A、B、C三个功能,通过『产品仓库』进行二次打包后,支持了A、B、C、D四项功能。
文本要讲的就是上面的『方法三』,下面开始详细说明实现细节。
项目介绍
项目 Android-SecBuild 基于 方法三 在rockchip平台上实现了二次构建方案。
项目包含『Android仓库』的构建脚本和『产品仓库』的构建脚本,目录结构如下:
├─Android Android仓库
│ ├─build Android构建脚本
│ ├─device device目录
│ │ └─DEFAULT 每个目录代表一个device,里面包含config.ini用于配置uboot config、kernel config、dts
│ └─outputs 构建结果
│
└─Product 产品仓库
├─build 二次构建脚本
├─outputs 构建结果
├─platform 将二次开发包拷贝至此目录
└─product 产品目录(里面每一个目录代表一个产品)
├─DEFAULT DEFAULT产品
└─PARENT PARENT产品
Android仓库
集成构建脚本
将 Android-SecBuild 项目中『Android』目录拷贝到Android源码根目录下,并重命名为『secbuild』,如下:
├─Android
......
├─external
├─frameworks
├─hardware
├─kernel
├─uboot
├─pakcages
├─system
......
└─secbuild 新增
├─build
| ......
| ├─build.sh
| ├─full_build.sh
| ├─pack.sh
| ......
├─device
| ├─DEFAULT
| └config.ini
└─outputs
build 目录下为构建脚本,里面包含三个主要脚本(其它脚本及工具是rockchip平台相关的,请根据平台确定要否需要),分别为:full_build.sh、build.sh、pack.sh。
● full_build.sh 负责调用build.sh和pack.sh。
● build.sh 编译Android源码。
● pack.sh 将Android源码编译产物和二次打包所需工具打包成二次开发包。
device/DEFAULT 下config.ini文件用于配置uboot config、kernel config和dts,内容如下:
# u-boot config
UBOOT_DEFCONFIG=default_defconfig
# kernel config
KERNEL_DEFCONFIG=default_defconfig
# kernel dts
KERNEL_DTS=default_dts
outputs 目录为构建结果,包含Android源码编译生成的各种img和二次开发包等。
生成二次开发包
执行 secbuild/build/full_build.sh 脚本编译Android系统并打包二次开发包。