VNDK 定义工具可帮助供应商将其源代码树迁移到 Android 8.0 环境。此工具会扫描系统和供应商映像中的二进制文件,然后解析依赖项。根据模块依赖关系图,此工具还可以检测到违反 VNDK 概念的行为,并为在分区之间移动模块提供见解/建议。如果指定了通用系统映像 (GSI),VNDK 定义工具可以将您的系统映像与 GSI 进行比较,并确定扩展库。
本节介绍 VNDK 定义工具常用的三个命令
vndk
。计算 Android 8.0 及更高版本中构建系统变通方法的 VNDK_SP_LIBRARIES、VNDK_SP_EXT_LIBRARIES 和 EXTRA_VENDOR_LIBRARIES。check-dep
。检查从供应商模块到不符合条件的框架共享库的违规模块依赖关系。deps
。打印共享库和可执行文件之间的依赖关系。
如需详细了解高级命令用法,请参阅 VNDK Definition Tool 代码库中的 README.md 文件。
vndk
vndk
子命令从系统分区和供应商分区加载共享库和可执行文件,然后解析模块依赖关系,以确定必须复制到 /system/lib[64]/vndk-sp-${VER}
和 /vendor/lib[64]
的库。vndk
子命令的选项包括:
选项 | 说明 |
---|---|
--system |
指向包含系统分区中文件的目录。 |
--vendor |
指向包含供应商分区中文件的目录。 |
--aosp-system |
指向包含通用系统映像 (GSI) 中文件的目录。 |
--load-extra-deps |
指向描述隐式依赖关系(例如 dlopen() )的文件。 |
例如,要计算 VNDK 库集,请运行以下 vndk
子命令:
./vndk_definition_tool.py vndk \
--system ${ANDROID_PRODUCT_OUT}/system \
--vendor ${ANDROID_PRODUCT_OUT}/vendor \
--aosp-system ${ANDROID_PRODUCT_OUT}/../generic_arm64_ab/system\
--load-extra-deps dlopen.dep
使用简单的文件格式指定额外的依赖项。每行表示一个关系,冒号前面的文件依赖于冒号后面的文件。例如:
/system/lib/libart.so: /system/lib/libart-compiler.so
此行让 VNDK 定义工具知道 libart.so
依赖于 libart-compiler.so
。
安装目标位置
VNDK 定义工具列出了以下类别的库和相应的安装目录:
类别 | 目录 |
---|---|
vndk_sp | 必须安装到 /system/lib[64]/vndk-sp-${VER} |
vndk_sp_ext | 必须安装到 /vendor/lib[64]/vndk-sp |
extra_vendor_libs | 必须安装到 /vendor/lib[64] |
构建系统模板
从 VNDK 定义工具收集输出后,供应商可以创建一个 Android.mk
文件,并在其中填写 VNDK_SP_LIBRARIES
、VNDK_SP_EXT_LIBRARIES
和 EXTRA_VENDOR_LIBRARIES
,以自动执行将库复制到指定安装目标位置的过程。
ifneq ($(filter $(YOUR_DEVICE_NAME),$(TARGET_DEVICE)),) VNDK_SP_LIBRARIES := ##_VNDK_SP_## VNDK_SP_EXT_LIBRARIES := ##_VNDK_SP_EXT_## EXTRA_VENDOR_LIBRARIES := ##_EXTRA_VENDOR_LIBS_## #------------------------------------------------------------------------------- # VNDK Modules #------------------------------------------------------------------------------- LOCAL_PATH := $(call my-dir) define define-vndk-lib include $$(CLEAR_VARS) LOCAL_MODULE := $1.$2 LOCAL_MODULE_CLASS := SHARED_LIBRARIES LOCAL_PREBUILT_MODULE_FILE := $$(TARGET_OUT_INTERMEDIATE_LIBRARIES)/$1.so LOCAL_STRIP_MODULE := false LOCAL_MULTILIB := first LOCAL_MODULE_TAGS := optional LOCAL_INSTALLED_MODULE_STEM := $1.so LOCAL_MODULE_SUFFIX := .so LOCAL_MODULE_RELATIVE_PATH := $3 LOCAL_VENDOR_MODULE := $4 include $$(BUILD_PREBUILT) ifneq ($$(TARGET_2ND_ARCH),) ifneq ($$(TARGET_TRANSLATE_2ND_ARCH),true) include $$(CLEAR_VARS) LOCAL_MODULE := $1.$2 LOCAL_MODULE_CLASS := SHARED_LIBRARIES LOCAL_PREBUILT_MODULE_FILE := $$($$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_INTERMEDIATE_LIBRARIES)/$1.so LOCAL_STRIP_MODULE := false LOCAL_MULTILIB := 32 LOCAL_MODULE_TAGS := optional LOCAL_INSTALLED_MODULE_STEM := $1.so LOCAL_MODULE_SUFFIX := .so LOCAL_MODULE_RELATIVE_PATH := $3 LOCAL_VENDOR_MODULE := $4 include $$(BUILD_PREBUILT) endif # TARGET_TRANSLATE_2ND_ARCH is not true endif # TARGET_2ND_ARCH is not empty endef $(foreach lib,$(VNDK_SP_LIBRARIES),\ $(eval $(call define-vndk-lib,$(lib),vndk-sp-gen,vndk-sp,))) $(foreach lib,$(VNDK_SP_EXT_LIBRARIES),\ $(eval $(call define-vndk-lib,$(lib),vndk-sp-ext-gen,vndk-sp,true))) $(foreach lib,$(EXTRA_VENDOR_LIBRARIES),\ $(eval $(call define-vndk-lib,$(lib),vndk-ext-gen,,true))) #------------------------------------------------------------------------------- # Phony Package #------------------------------------------------------------------------------- include $(CLEAR_VARS) LOCAL_MODULE := $(YOUR_DEVICE_NAME)-vndk LOCAL_MODULE_TAGS := optional LOCAL_REQUIRED_MODULES := \ $(addsuffix .vndk-sp-gen,$(VNDK_SP_LIBRARIES)) \ $(addsuffix .vndk-sp-ext-gen,$(VNDK_SP_EXT_LIBRARIES)) \ $(addsuffix .vndk-ext-gen,$(EXTRA_VENDOR_LIBRARIES)) include $(BUILD_PHONY_PACKAGE) endif # ifneq ($(filter $(YOUR_DEVICE_NAME),$(TARGET_DEVICE)),)
check-dep
check-dep
子命令扫描供应商模块并检查其依赖关系。如果检测到违规行为,它会打印违规的依赖库和符号用法。
./vndk_definition_tool.py check-dep \
--system ${ANDROID_PRODUCT_OUT}/system \
--vendor ${ANDROID_PRODUCT_OUT}/vendor \
--tag-file eligible-list.csv \
--module-info ${ANDROID_PRODUCT_OUT}/module-info.json \
1> check_dep.txt \
2> check_dep_err.txt
例如,以下示例输出显示了从 libRS_internal.so
到 libmediandk.so
的违规依赖关系:
/system/lib/libRS_internal.so MODULE_PATH: frameworks/rs /system/lib/libmediandk.so AImageReader_acquireNextImage AImageReader_delete AImageReader_getWindow AImageReader_new AImageReader_setImageListener
check-dep
子命令的选项包括:
选项 | 说明 |
---|---|
--tag-file |
必须引用符合条件的库标记文件(如下所述),这是一个 Google 提供的电子表格,其中描述了框架共享库的类别。 |
--module-info |
指向 Android 构建系统生成的 module-info.json 文件。它帮助 VNDK 定义工具将二进制模块与源代码关联起来。 |
符合条件的库标记文件
Google 提供了一个符合条件的 VNDK 电子表格(例如 eligible-list.csv
),用于标记可供供应商模块使用的框架共享库。
标记 | 说明 |
---|---|
LL-NDK | 具有稳定 ABI/API 的共享库,可供框架模块和供应商模块使用。 |
LL-NDK-Private | LL-NDK 库的私有依赖项。供应商模块不得直接访问这些库。 |
VNDK-SP | SP-HAL 框架共享库依赖项。 |
VNDK-SP-Private | 并非所有供应商模块都可直接访问的 VNDK-SP 依赖项。 |
VNDK | 可供供应商模块使用的框架共享库(SP-HAL 和 SP-HAL-Dep 除外)。 |
VNDK-Private | 并非所有供应商模块都可直接访问的 VNDK 依赖项。 |
FWK-ONLY | 框架专用共享库,供应商模块不得访问(无论是直接还是间接访问)。 |
FWK-ONLY-RS | 框架专用共享库,供应商模块不得访问(RS 用法除外)。 |
下表描述了用于供应商共享库的标记:
标记 | 说明 |
---|---|
SP-HAL | 同进程 HAL 实现共享库。 |
SP-HAL-Dep | SP-HAL 供应商共享库依赖项(也称为 SP-HAL 依赖项,不包括 LL-NDK 和 VNDK-SP)。 |
VND-ONLY | 框架不可见的共享库,框架模块不得访问。复制的扩展 VNDK 库也标记为 VND-ONLY。 |
标记之间的关系

图 1. 标记之间的关系。
deps
为了调试库依赖关系,deps
子命令会打印模块依赖关系。
./vndk_definition_tool.py deps \
--system ${ANDROID_PRODUCT_OUT}/system \
--vendor ${ANDROID_PRODUCT_OUT}/vendor
输出由多行组成。没有制表符的行表示新节的开始。带有制表符的行依赖于上一节。例如:
/system/lib/ld-android.so /system/lib/libc.so /system/lib/libdl.so
此输出表明 ld-android.so
没有依赖项,而 libc.so
依赖于 libdl.so
。
当指定 --revert
选项时,deps
子命令会打印库的用法(反向依赖关系)。
./vndk_definition_tool.py deps \
--revert \
--system ${ANDROID_PRODUCT_OUT}/system \
--vendor ${ANDROID_PRODUCT_OUT}/vendor
例如:
/system/lib/ld-android.so /system/lib/libdl.so
此输出表明 ld-android.so
被 libdl.so
使用,或者换句话说,libdl.so
依赖于 ld-android.so
。此外,此输出表明 libdl.so
是 ld-android.so
的唯一用户。
当指定 --symbol
选项时,deps
子命令会打印正在使用的符号。
./vndk_definition_tool.py deps \
--symbol \
--system ${ANDROID_PRODUCT_OUT}/system \
--vendor ${ANDROID_PRODUCT_OUT}/vendor
例如:
/system/lib/libc.so /system/lib/libdl.so android_get_application_target_sdk_version dl_unwind_find_exidx dlclose dlerror dlopen dlsym
此输出表明 libc.so
依赖于从 libdl.so
导出的六个函数。如果同时指定 --symbol
选项和 --revert
选项,则会打印用户使用的符号。