减小 OTA 大小

本页介绍了为减少不同构建之间的不必要文件变更,而添加到 AOSP 的构建变更。维护自己的构建系统的设备实现人员,可依照此信息减小无线 (OTA) 更新的大小。

有时 Android OTA 包含的变更文件并非对应于代码变更,而是对应于构建系统的软件工件。在不同时间、不同目录或不同机器上构建相同代码时,会产生大量变更文件,这时便会发生上述情况。这些多余的文件不仅会增加 OTA 的大小,而且会导致难以确定 OTA 中发生变更的代码。

为了使 OTA 的内容更加透明,AOSP 加入了构建系统变更,旨在通过消除不同构建之间不必要的文件变更来减小 OTA 的大小。这样做是为了减小 OTA 的大小,使其只包括与 OTA 中包含的补丁程序相关的文件。AOSP 还会加入构建 diff 工具,以过滤出常见的构建相关文件变更并提供更加清晰的构建文件 diff。

构建系统可能会通过多种方式创建不必要的文件 diff。下文讨论了其中一些问题和解决方案,并尽可能提供了 AOSP 中的修复示例。

文件顺序

问题:文件系统在请求目录中的文件列表时,并不保证文件顺序,尽管对于同一查询,文件顺序通常是相同的。诸如 ls 之类的工具在默认情况下会对结果进行排序,但 findmake 之类的命令使用的通配符函数却不会对结果进行排序。用户在使用此类工具之前,必须对输出进行排序。

解决方案:用户在使用带有通配符的 findmake 之类的工具之前,必须对这些命令的输出进行排序。要在 Android.mk 文件中使用 $(wildcard )$(shell find ),也应该进行排序。有些工具(例如 Java)确实会对输入进行排序,因此有必要对排序进行验证。

示例:很多实例使用内建的 all-*-files-under 宏固定在核心构建系统中,其中包括 all-cpp-files-under(一些定义分散在其他 makefile 中)。有关详情,请参阅以下 CL:

构建目录

问题:变更构建内容所在的目录会导致二进制文件有所变化。Android 构建中的大多数路径是相对路径,因此 C/C ++ 中的 __FILE__ 不是问题。不过,默认情况下调试符号会对完整的路径名进行编码,而对预剥离二进制文件进行哈希处理会生成 .note.gnu.build-id,因此调试符号变更会使二进制文件发生变化。

解决方案:AOSP 现在会使调试路径变成相对路径。有关详情,请参阅 CL: https://android.googlesource.com/platform/build/+/6a66a887baadc9eb3d0d60e26f748b8453e27a02

时间戳

问题:构建输出中的时间戳会导致不必要的文件变更。这可能发生在以下位置:

  • C 或 C++ 代码中的 __DATE__/__TIME__/__TIMESTAMP__ 宏。
  • 基于 ZIP 的归档中嵌入的时间戳。

解决方案/示例:要从构建输出中移除时间戳,请遵循下文中的说明操作。

C/C++ 中的 __DATE__/__TIME__/__TIMESTAMP__

这些宏总是会为不同的构建生成不同的输出,因此不应使用。 您可选择以下方法来消除这些宏:

注意:我们开启了 -Werror=date-time,因此使用时间戳是一种构建错误。

归档(zip、jar)中的嵌入时间戳

我们通过将 -X 添加到 zip 命令的所有用例中,解决了嵌入时间戳的问题,因此构建工具的 UID/GID 和扩展的 Unix 时间戳不会嵌入到 ZIP 文件中。

新工具 ziptime(位于 /platform/build/+/master/tools/ziptime/)会重置 zip 标头中的正常时间戳。有关详情,请参阅 README 文件

signapk 工具为 APK 文件设置的时间戳可能因服务器所在的时区而异。有关详情,请参阅 CL: https://android.googlesource.com/platform/build/+/6c41036bcf35fe39162b50d27533f0f3bfab3028

版本字符串

问题:APK 版本字符串通常包含附加到硬编码版本的 BUILD_NUMBER。即使 APK 中并未发生任何其他变更,APK 仍然会有所不同。

解决方案:从 APK 版本字符串中移除版本号。

示例:

一致的构建工具

问题:生成安装文件的工具必须一致(相同的输入应始终产生相同的输出)。

解决方案/示例:以下构建工具需要进行变更:

使用构建 diff 工具

对于无法消除构建相关文件变更的情况,我们提供构建 diff 工具 target_files_diff.py 来比较两个文件包。该工具会在两个构建之间执行递归 diff,从而排除常见的构建相关文件变更,例如:

  • 构建输出中的预期变更(例如,由于版本号变更所导致)。
  • 由于当前构建系统中的已知问题所导致的变更。

要使用构建 diff 工具,请运行以下命令:

$ target_files_diff.py dir1 dir2

dir1dir2 是包含每个构建的提取目标文件的基础目录。