VNDK 定义工具可帮助供应商将其源代码树迁移到 Android 8.0 环境。该工具会先扫描系统映像及供应商映像中的二进制文件,然后解析依赖项。若有模块依赖项图为依据,该工具还可检测出不符合 VNDK 概念的行为,以及为在分区之间移动模块提供分析数据/建议。如果指定了常规系统映像 (GSI),VNDK 定义工具便可将您的系统映像与 GSI 进行比较,从而确定扩展后的库。
本部分将介绍 VNDK 定义工具常用的 3 个命令:
vndk
:为 Android 8.0 及更高版本中的构建系统权宜解决方法计算 VNDK_SP_LIBRARIES、VNDK_SP_EXT_LIBRARIES 和 EXTRA_VENDOR_LIBRARIES。check-dep
:检查是否有违规模块依赖项(从供应商模块指向不符合条件的框架共享库)。deps
:显示共享库与可执行文件之间的依赖关系。
要详细了解高级命令用法,请参阅 VNDK 定义工具代码库中的 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 | Same-Process 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
此输出信息表明:libdl.so
使用了 ld-android.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
导出的 6 个函数。如果同时指定了 --symbol
选项和 --revert
选项,则会输出使用者所用的符号。