生成 VNDK 快照

VNDK 快照是一组适用于 Android 版本的 VNDK-core 和 VNDK-SP 库。如果 system.img 包含 vendor.img 所需的相应 VNDK 快照,那么,您只能升级系统分区。

正式的 VNDK 快照是在 Android 编译服务器上自动编译而成,并签入 Android 源代码树的 /prebuilts/vndk 中。为了便于开发,您可以在本地编译 VNDK 快照。arm、arm64、x86 和 x86_64 TARGET_ARCH 架构支持 VNDK 快照。

快照编译工件

Android 编译服务器使用以下编译参数和编译命令,生成适用于 VNDK 快照的编译工件。

编译参数

编译目标名称为 vndk,编译目标配置如下所示:

  • TARGET_PRODUCT=aosp_{TARGET_ARCH}_ab
  • TARGET_BUILD_VARIANT=user
  • TARGET_ARCH。与常规系统映像 (GSI) 目标架构(arm、arm64、x86、x86_64)相同。
  • TARGET_ARCH_VARIANT。对于快照 v27 (Android 8.1),变体包含热门配置(如下所示);未来版本可能会包含其他 arch/cpu 变体。
TARGET_PRODUCT TARGET_ARCH TARGET_ARCH_VARIANT
aosp_arm_ab arm armv7-a-neon
aosp_arm64_ab arm64 armv8-a
aosp_x86_ab x86 x86
aosp_x86_64_ab x86_64 x86_64

编译命令

对于正式快照,Android 9 在 vndk.mk 中引入了新的虚拟目标 (vndk),该目标会编译 VNDK 快照并将其输出到 $DIST_DIR 中。快照的 ZIP 文件采用 android-vndk-{TARGET_ARCH}.zip 格式。例如:

$ lunch aosp_<ARCH>_ab-user
$ make -j vndk dist [BOARD_VNDK_VERSION=current]

Android 编译服务器通过以下命令使用 build.sh 脚本来编译所有受支持的架构类型:

$ DIST_DIR=%dist_dir% development/vndk/snapshot/build.sh

Android 版本的 VNDK 快照由 <Android Version>-release 分支生成。

在本地编译

在开发过程中,您可以通过以下命令,从本地源代码树中编译 VNDK 快照:

  • 要一次编译所有受支持的架构,请通过以下命令执行编译脚本 (build.sh):
    $ cd $ANDROID_BUILD_TOP
    $ development/vndk/snapshot/build.sh
    
  • 要编译某个特定的 TARGET_ARCH,请执行以下命令:
    $ lunch aosp_<ARCH>_ab-user
    $ m -j vndk dist
    

相应的 android-vndk-<ARCH>.zip 文件会在 $DIST_DIR 下创建。

快照文件

VNDK 快照包含以下文件:

  • VNDK-core 和 VNDK-SP 共享库的供应商变体。
    • 无需 LL-NDK 共享库,因为这类库是向后兼容的。
    • 对于 64 位目标,TARGET_ARCH 和 TARGET_2ND_ARCH 库都将被编译并包含在内。
  • VNDK-core、VNDK-SP、LL-NDK 和 VNDK-private 库的列表位于 [vndkcore|vndksp|llndk|vndkprivate].libraries.txt
  • 链接器配置文件为 ld.config.txt
  • 许可文件。
  • module_paths.txt。记录所有 VNDK 库的模块路径;检查 GPL 项目是否已在指定 Android 源代码树中发布源代码时,需要用到这种文件。

对于指定 VNDK 快照 ZIP 文件 android-vndk-{TARGET_ARCH}.zip,系统会根据 ABI 位数将 VNDK 预编译库分组到名为 arch-{TARGET_ARCH}-{TARGET_ARCH_VARIANT} 的单独目录中。例如,对于 android-vndk-arm64.zip,64 位库会位于 arch-arm64-armv8-a 下,而 32 位库则位于 arch-arm-armv8-a 下。

示例:VNDK 快照目录结构

以下示例展示了 arm64 (TARGET_ARCH=arm64) VNDK 快照 ZIP 文件 (android-vndk-arm64.zip) 的目录结构。

图 1. VNDK 快照目录结构(示例)

上传 VNDK 快照

VNDK 快照将签入 /prebuilts/vndk/v<VER> 下的源代码树,其中 <VER> 为 VNDK 快照的版本(遵循相应 Android 版本的 SDK 版本)。例如,O MR1 VNDK 快照的版本为 27。

使用 update.py 脚本

update.py 脚本 (/development/vndk/snapshot/update.py) 可自动将预编译的 VNDK 快照添加到源代码树中。此脚本将执行以下任务:

  1. /prebuilts/vndk/v<VER> 中,使用 repo start 创建新的 git 分支。
  2. 获取 VNDK 快照编译软件工件并将其解压缩。
  3. 运行 gen_buildfiles.py 以自动生成编译文件(Android.mkAndroid.bp)。
  4. 运行 check_gpl_license.py 以验证根据通用公共许可证 (GPL) 获得许可的预编译库是否在当前源代码树中发布了源代码。
  5. 使用 git commit 提交新的更改。

使用本地编译的 VNDK 快照

在开发过程中,您可以使用本地编译的 VNDK 快照进行测试。在指定 --local 选项的情况下,update.py 会从本地 $DIST_DIR(而非 Android 编译服务器中)提取 VNDK 快照编译工件。用法如下:

$ python update.py <VER> --local

例如,要使用本地编译软件工件更新 O MR1 VNDK 快照,请运行以下命令:

$ python update.py 27 --local

由于本地模式仅用于测试,因此该脚本将跳过 GPL 许可检查和 git commit 步骤。

prebuilts/vndk 的目录结构

图 2. Prebuilts/vndk 目录结构

安装 VNDK 快照

系统映像在编译时使用 BOARD_VNDK_VERSIONPRODUCT_EXTRA_VNDK_VERSIONSro.vndk.version 中的信息安装 VNDK 快照库。您可以使用以下选项之一控制从 /prebuilts/vndk/v<VER> 中安装哪些 VNDK 快照:

  • 选项 1BOARD_VNDK_VERSION。使用快照模块编译当前供应商模块,并仅安装供应商模块所需的快照模块。
  • 选项 2PRODUCT_EXTRA_VNDK_VERSIONS。无论当前供应商模块有哪些,都安装 VNDK 快照模块。这将安装 PRODUCT_EXTRA_VNDK_VERSIONS 中列出的预编译 VNDK 快照,而不会在编译时将其与任何其他模块相关联。

设置 BOARD_VNDK_VERSION

BOARD_VNDK_VERSION 显示的是当前供应商模块需要编译的 VNDK 版本。如果 BOARD_VNDK_VERSION/prebuilts/vndk 目录中有可用的 VNDK 快照版本,则系统会安装 BOARD_VNDK_VERSION 中指明的 VNDK 快照。如果目录中的 VNDK 快照不可用,则会出现编译错误。

定义 BOARD_VNDK_VERSION 也会启用要安装的 VNDK 模块。供应商模块会在编译时与 BOARD_VNDK_VERSION 中定义的 VNDK 快照版本相关联(此操作不会在系统源代码中编译当前的 VNDK 模块)。从代码库中下载完整的源代码树时,系统源代码和供应商源代码均基于相同的 Android 版本。

设置 PRODUCT_EXTRA_VNDK_VERSIONS

PRODUCT_EXTRA_VNDK_VERSIONS 列出了要安装的其他 VNDK 版本。正常情况下,当前的供应商分区只需一个 VNDK 快照就足够了。不过,在某些情况下,您可能需要在一个系统映像中提供多个快照。例如,常规系统映像 (GSI) 具有多个快照,以通过一个系统映像支持多个供应商版本。设置 PRODUCT_EXTRA_VNDK_VERSIONS 后,除了 BOARD_VNDK_VERSION 中的 VNDK 版本之外,您还可以安装 VNDK 快照模块。

如果 PRODUCT_EXTRA_VNDK_VERSIONS 具有特定的版本列表,则编译系统会在 prebuilts/vndk 目录中查找版本列表的预编译快照。如果编译系统找到所有列出的快照,便会将这些快照文件安装到每个 out/target/product/<board>/system/lib[64]/vndk[-sp]-${VER} 中。缺少某些版本会导致出现编译错误。

VNDK 模块将不会在编译时与供应商模块相关联,但在运行时可能会使用该模块(如果供应商分区中的供应商模块需要某个已安装的 VNDK 版本)。PRODUCT_EXTRA_VNDK_VERSIONS 仅在指定了 BOARD_VNDK_VERSION 的情况下才有效。例如,要将 O MR1 VNDK 快照安装到 system.img 中,请运行以下命令:

$ m -j PRODUCT_EXTRA_VNDK_VERSIONS=27

PLATFORM_VNDK_VERSION

PLATFORM_VNDK_VERSION 在系统源代码中指定了当前 VNDK 模块的 VNDK 版本。系统会通过以下方式自动设置该值:

  • 在版本发布之前,将 PLATFORM_VNDK_VERSION 设置为 PLATFORM_VERSION_CODENAME
  • 在发布时,将 PLATFORM_SDK_VERSION 复制到 PLATFORM_VNDK_VERSION 中。

发布 Android 版本后,当前的 VNDK 库会被安装到 /system/lib[64]/vndk-$SDK_VER/system/lib[64]/vndk-sp-$SDK_VER,其中 $SDK_VER 是存储在 PLATFORM_VNDK_VERSION 中的版本。

命名空间配置

供应商模块使用 /etc/ld.config.${VER}.txt(其中 ${VER} 是从 ro.vndk.version 属性中获得的)中的命名空间配置来搜索所需的共享库。命名空间配置中包含带有版本编号的 VNDK 目录,该目录使用以下语法:

  • /system/${LIB}/vndk-%VNDK_VER%
  • /system/${LIB}/vndk-sp-%VNDK_VER%

%VNDK_VER% 在编译时会被替换为 PLATFORM_VNDK_VERSION,这样一来,系统映像便能够为每个 VNDK 版本提供多个快照。

如果将 BOARD_VNDK_VERSION 设置为 current,则 PLATFORM_VNDK_VERSION 将存储在 ro.vndk.version 中;否则,BOARD_VNDK_VERSION 将存储在 ro.vndk.version 中。PLATFORM_VNDK_VERSION 在 Android 版本发布时会被设置为 SDK 版本;在发布之前,由字母和数字组成的 Android 代码名称会用于 PLATFORM_VNDK_VERSION

VNDK 版本设置摘要

下表总结了 VNDK 版本设置。

供应商
版本
开发板
版本
SDK
版本
平台
版本
版本
属性
安装目录
当前的 VNDK 模块 current 之前 <CODE_NAME> <CODE_NAME> /system/lib[64]/vndk[-sp]-<CODE_NAME>
之后 <SDK_ver> <SDK_ver> /system/lib[64]/vndk[-sp]-<SDK_ver>
预编译的快照模块 <VNDK_ver>
(用于快照)
之前或之后 <CODE_NAME>
或 <SDK_ver>
<VNDK_ver> /system/lib[64]/vndk[-sp]-<VNDK_ver>
  • 开发板版本 (BOARD_VNDK_VERSION):供应商模块需要编译的 VNDK 版本。如果供应商模块可与当前系统模块相关联,则将其设置为 current
  • 平台版本 (PLATFORM_VNDK_VERSION):当前系统模块正在编译的 VNDK 版本(仅在 BOARD_VNDK_VERSION 为当前版本时编译)。
  • 版本属性 (ro.vndk.version):一种属性,用于指定 vendor.img 中的二进制文件和库需要运行的 VNDK 版本。该属性存储在 /vendor/default.prop 下的 vendor.img 中。