在 Android 8.1 以上版本中,建構系統內建 VNDK 支援功能。時間 已啟用 VNDK 支援,建構系統會檢查 模組,為供應商模組建構供應商專屬的變化版本 這些模組會自動安裝到指定的目錄。
VNDK 版本支援範例
在這個範例中,Android.bp
模組定義定義了
名為 libexample
的程式庫。vendor_available
屬性代表架構模組和供應商模組可能會依賴
libexample
:
圖 1. 支援已啟用。
架構可執行 /system/bin/foo
和供應商
可執行檔的 /vendor/bin/bar
依附於 libexample
在 shared_libs
屬性中使用 libexample
。
如果架構模組和供應商都使用 libexample
模組,即建構兩個 libexample
的變化版本。核心變化版本
(以 libexample
命名) 由架構模組和
供應商使用供應商子類 (以 libexample.vendor
命名)
模組。這兩個變化版本會安裝至不同的目錄:
- 核心變化版本的安裝位置
/system/lib[64]/libexample.so
。 - 供應商子類已安裝至 VNDK APEX,因為
vndk.enabled
為true
。
詳情請參閱「模組定義」。
設定建構支援
如要啟用產品裝置的完整建構系統支援,請新增
BOARD_VNDK_VERSION
至 BoardConfig.mk
:
BOARD_VNDK_VERSION := current
這項設定具有「全域」效果:如果在
BoardConfig.mk
,所有模組皆已勾選。我們並未提供機制
將違規的模組加入黑名單或加入許可清單,
加入 BOARD_VNDK_VERSION
之前不需要的依附元件。個人中心
只要在BOARD_VNDK_VERSION
環境變數:
$ BOARD_VNDK_VERSION=current m module_name.vendor
啟用 BOARD_VNDK_VERSION
時,會有多個預設全域通用
標頭搜尋路徑會「移除」。其中包括:
frameworks/av/include
frameworks/native/include
frameworks/native/opengl/include
hardware/libhardware/include
hardware/libhardware_legacy/include
hardware/ril/include
libnativehelper/include
libnativehelper/include_deprecated
system/core/include
system/media/audio/include
如果模組依附於這些目錄的標頭,您必須指定
(明確) 使用 header_libs
建立依附元件。
static_libs
和/或 shared_libs
。
越南盾
在 Android 10 以下版本中,已安裝 vndk.enabled
的模組
/system/lib[64]/vndk[-sp]-${VER}
。在 Android 11 以上版本中,
VNDK 程式庫以 APEX 格式封裝,VNDK APEX 的名稱為
com.android.vndk.v${VER}
。視裝置設定而定
VNDK APEX 採用整併或未整併的形式,且可從標準路徑取得
/apex/com.android.vndk.v${VER}
。
圖 2. VNDK APEX。
模組定義
如要使用 BOARD_VNDK_VERSION
建構 Android,您必須修改
Android.mk
或
Android.bp
。本節說明不同類型的模組
定義、多個 VNDK 相關模組屬性,以及依附元件檢查
建構系統
供應商模組
供應商模組是供應商專屬的執行檔或共用程式庫,
必須安裝到供應商分區中。在 Android.bp
個檔案中,
供應商模組必須將供應商或專屬屬性設為「true
」。
在 Android.mk
檔案中,必須設定供應商模組
LOCAL_VENDOR_MODULE
或 LOCAL_PROPRIETARY_MODULE
到
true
。
如果已定義 BOARD_VNDK_VERSION
,建構系統會禁止
供應商模組與架構模組之間的依附元件,且在下列情況中會發出錯誤:
- 沒有
vendor:true
的模組依附於含有vendor:true
,或 - 包含
vendor:true
的模組依附於 非llndk_library
模組vendor:true
,或vendor_available:true
。
依附元件檢查適用於 header_libs
。
static_libs
,和 shared_libs
英寸
Android.bp
和LOCAL_HEADER_LIBRARIES
,
LOCAL_STATIC_LIBRARIES
和 LOCAL_SHARED_LIBRARIES
英寸
Android.mk
。
LL-NDK
LL-NDK 共用程式庫是採用穩定 ABI 的共用程式庫。兩個架構
和供應商模組共用最新實作項目。對於每項
LL-NDK 共用資料庫,cc_library
中會包含
含有符號檔案的 llndk
屬性:
cc_library { name: "libvndksupport", llndk: { symbol_file: "libvndksupport.map.txt", }, }
符號檔案說明供應商模組可以看見的符號。例如:
LIBVNDKSUPPORT { global: android_load_sphal_library; # llndk android_unload_sphal_library; # llndk local: *; };
建構系統會根據符號檔案,為
以及這些程式庫模組
已啟用「BOARD_VNDK_VERSION
」。虛設常式包含符號
共用程式庫的條件:
- 未在該部分中以
_PRIVATE
或_PLATFORM
, - 不含
#platform-only
標記,且 - 沒有
#introduce*
標記或是與 目標。
越南盾
在 Android.bp
個檔案 (cc_library
) 中,
cc_library_static
、cc_library_shared
和
cc_library_headers
模組定義支援三個 VNDK 相關
屬性:vendor_available
、vndk.enabled
和
vndk.support_system_process
。
如果 vendor_available
或 vndk.enabled
為
true
,兩個變體 (核心和供應商) 可能是
。核心變化版本應視為架構模組和廠商
變數應視為供應商模組。如果部分架構模組
核心變數是由這個單元建構而成如果某些供應商模組
必須建構供應商變化版本建構系統會強制執行
下列依附元件檢查:
- 核心變化版本一律僅限架構,供應商無法存取 模組。
- 架構模組一律無法存取供應商變化版本。
- 供應商子類的所有依附元件,
header_libs
、static_libs
和/或shared_libs
,必須是llndk_library
或vendor_available
或vndk.enabled
模組。 - 如果
vendor_available
為true
,就是供應商子類 所有供應商模組均可存取。 - 如果
vendor_available
為false
,就是供應商子類 只能供其他 VNDK 或 VNDK-SP 模組存取 (也就是說vendor:true
無法連結vendor_available:false
模組)。
cc_library
或
cc_library_shared
取決於下列規則:
- 核心變化版本會安裝至
/system/lib[64]
。 - 供應商變化版本的安裝路徑可能有所不同:
- 如果
vndk.enabled
為false
,就是供應商子類 已安裝至/vendor/lib[64]
。 - 如果
vndk.enabled
為true
,就是供應商子類 已安裝至 VNDK APEX(com.android.vndk.v${VER}
)。
- 如果
下表摘要說明建構系統如何處理供應商變化版本:
供應商可使用 | 已啟用 vndk |
vndk support_same_process |
供應商變化版本說明 |
---|---|---|---|
true |
false |
false |
供應商子類僅限 VND。共用程式庫是
已安裝至 /vendor/lib[64] 。 |
true |
無效 (建構錯誤) | ||
true |
false |
供應商子類為 VNDK。已安裝共用程式庫 變更為 VNDK APEX。 | |
true |
供應商子類為 VNDK-SP。共用程式庫是 已安裝至 VNDK APEX。 | ||
|
|
|
沒有供應商子類。本單元僅適用於 |
true |
無效 (建構錯誤) | ||
true |
false |
供應商子類為 VNDK-Private。共用程式庫是 已安裝至 VNDK APEX。不得出現 方便供應商模組直接使用 | |
true |
供應商子類為 VNDK-SP-Private。共用程式庫是 已安裝至 VNDK APEX。不得出現 方便供應商模組直接使用 |
VNDK 擴充功能
VNDK 擴充功能是 VNDK 共用程式庫與其他 API。副檔名是
已安裝至 /vendor/lib[64]/vndk[-sp]
(沒有版本後置字串)
並在執行階段覆寫原始 VNDK 共用程式庫
定義 VNDK 擴充功能
在 Android 9 以上版本中,Android.bp
原生支援 VNDK
。如要建構 VNDK 擴充功能,請使用
vendor:true
和 extends
屬性:
cc_library { name: "libvndk", vendor_available: true, vndk: { enabled: true, }, } cc_library { name: "libvndk_ext", vendor: true, vndk: { enabled: true, extends: "libvndk", }, }
具有 vendor:true
、vndk.enabled:true
和
extends
屬性會定義 VNDK 擴充功能:
extends
屬性必須指定基礎 VNDK 共用資料庫 name (或 VNDK-SP 共用程式庫名稱),- VNDK 擴充功能 (或 VNDK-SP 擴充功能) 是以基本模組命名
從擴充到擴充的另一個名稱例如,
libvndk_ext
是libvndk.so
,而不是libvndk_ext.so
。 - VNDK 擴充功能已安裝至
/vendor/lib[64]/vndk
。 - VNDK-SP 擴充功能已安裝至
/vendor/lib[64]/vndk-sp
。 - 基本共用程式庫必須同時包含
vndk.enabled:true
和vendor_available:true
。
VNDK-SP 擴充功能必須從 VNDK-SP 共用資料庫擴充
(vndk.support_system_process
必須相等):
cc_library { name: "libvndk_sp", vendor_available: true, vndk: { enabled: true, support_system_process: true, }, } cc_library { name: "libvndk_sp_ext", vendor: true, vndk: { enabled: true, extends: "libvndk_sp", support_system_process: true, }, }
VNDK 擴充功能 (或 VNDK-SP 擴充功能) 可能會依附於其他供應商共用 程式庫:
cc_library { name: "libvndk", vendor_available: true, vndk: { enabled: true, }, } cc_library { name: "libvndk_ext", vendor: true, vndk: { enabled: true, extends: "libvndk", }, shared_libs: [ "libvendor", ], } cc_library { name: "libvendor", vendor: true, }
使用 VNDK 擴充功能
如果供應商模組依賴 VNDK 擴充功能定義的其他 API,
模組必須在其依附元件中指定 VNDK 擴充功能的名稱
shared_libs
屬性:
// A vendor shared library example cc_library { name: "libvendor", vendor: true, shared_libs: [ "libvndk_ext", ], } // A vendor executable example cc_binary { name: "vendor-example", vendor: true, shared_libs: [ "libvndk_ext", ], }
如果供應商模組需要使用 VNDK 擴充功能,則這些 VNDK 擴充功能
已自動安裝至「/vendor/lib[64]/vndk[-sp]
」。如果模組
不再需要使用 VNDK 擴充功能,請將簡潔的步驟加入
CleanSpec.mk
即可移除共用資料庫。例如:
$(call add-clean-step, rm -rf $(TARGET_OUT_VENDOR)/lib/libvndk.so)
條件編譯
本節說明如何處理細微差異 (例如 在其中一個變化版本中加入或移除特徵), 三個 VNDK 共用程式庫:
- 核心變化版本 (例如
/system/lib[64]/libexample.so
) - 供應商子類 (例如
/apex/com.android.vndk.v${VER}/lib[64]/libexample.so
) - VNDK 擴充功能 (例如
/vendor/lib[64]/vndk[-sp]/libexample.so
)
條件編譯器標記
Android 建構系統為供應商定義 __ANDROID_VNDK__
和 VNDK 擴充功能。你可以保護密碼
兩邊的 C 前置處理器防護:
void all() { } #if !defined(__ANDROID_VNDK__) void framework_only() { } #endif #if defined(__ANDROID_VNDK__) void vndk_only() { } #endif
除了 __ANDROID_VNDK__
之外,其他 cflags
或
cppflags
可在「Android.bp
」中指定。
已在以下位置指定 cflags
或 cppflags
:
target.vendor
是供應商子類專用,
舉例來說,下列 Android.bp
定義
libexample
和 libexample_ext
:
cc_library { name: "libexample", srcs: ["src/example.c"], vendor_available: true, vndk: { enabled: true, }, target: { vendor: { cflags: ["-DLIBEXAMPLE_ENABLE_VNDK=1"], }, }, } cc_library { name: "libexample_ext", srcs: ["src/example.c"], vendor: true, vndk: { enabled: true, extends: "libexample", }, cflags: [ "-DLIBEXAMPLE_ENABLE_VNDK=1", "-DLIBEXAMPLE_ENABLE_VNDK_EXT=1", ], }
以下是 src/example.c
的程式碼清單:
void all() { } #if !defined(LIBEXAMPLE_ENABLE_VNDK) void framework_only() { } #endif #if defined(LIBEXAMPLE_ENABLE_VNDK) void vndk() { } #endif #if defined(LIBEXAMPLE_ENABLE_VNDK_EXT) void vndk_ext() { } #endif
根據這兩個檔案,建構系統會產生共用程式庫 包含下列匯出符號:
安裝路徑 | 已匯出的符號 |
---|---|
/system/lib[64]/libexample.so |
all 、framework_only |
/apex/com.android.vndk.v${VER}/lib[64]/libexample.so |
all 、vndk |
/vendor/lib[64]/vndk/libexample.so |
all 、vndk 、vndk_ext |
匯出符號相關規定
VNDK ABI 檢查工具
比較 VNDK 供應商變體的 ABI,以及
可對參照 ABI 傾印的參考 ABI 傾印的 VNDK 擴充功能
prebuilts/abi-dumps/vndk
。
- VNDK 供應商變化版本匯出的符號 (例如
/apex/com.android.vndk.v${VER}/lib[64]/libexample.so
) 必須相同 傳遞至 ABI 傾印中定義的符號 (非 的超集)。 - VNDK 擴充功能 (例如
/vendor/lib[64]/vndk/libexample.so
) 必須是 代表 ABI 傾印中定義的符號。
如果 VNDK 供應商變體或 VNDK 擴充功能不符合規定 ,VNDK ABI 檢查工具會發出建構錯誤並停止 建構應用程式
從供應商變數中排除來源檔案或共用資料庫
如要從供應商子類排除來源檔案,請將該檔案新增到
exclude_srcs
屬性。同樣地,確保共用程式庫
請將這些程式庫加入
exclude_shared_libs
屬性。例如:
cc_library { name: "libexample_cond_exclude", srcs: ["fwk.c", "both.c"], shared_libs: ["libfwk_only", "libboth"], vendor_available: true, target: { vendor: { exclude_srcs: ["fwk.c"], exclude_shared_libs: ["libfwk_only"], }, }, }
在這個範例中,libexample_cond_exclude
的核心變化版本
包含 fwk.c
和 both.c
的程式碼,且取決於
共用程式庫 libfwk_only
和 libboth
libexample_cond_exclude
的供應商子類只包含程式碼
從 both.c
排除,因為 fwk.c
已被排除
exclude_srcs
屬性。同樣地,這只取決於共用資料庫
libboth
,因為libfwk_only
被排除
exclude_shared_libs
屬性。
從 VNDK 擴充功能匯出標頭
VNDK 擴充功能可能會新增類別或新函式至 VNDK 共用 資源庫。建議將這些宣告保留在獨立的標頭中 並避免變更現有的標頭
例如:新的標頭檔案
已為 VNDK 建立 include-ext/example/ext/feature_name.h
擴充功能 libexample_ext
:
- Android.bp
- include-ext/example/ext/feature_name.h
- include/example/example.h
- src/example.c
- src/ext/feature_name.c
在下列Android.bp
中,有 libexample
個匯出項目
僅限 include
,libexample_ext
則會匯出兩者
include
和include-ext
。這可以確保
系統將不會誤將「feature_name.h
」
libexample
:
cc_library { name: "libexample", srcs: ["src/example.c"], export_include_dirs: ["include"], vendor_available: true, vndk: { enabled: true, }, } cc_library { name: "libexample_ext", srcs: [ "src/example.c", "src/ext/feature_name.c", ], export_include_dirs: [ "include", "include-ext", ], vendor: true, vndk: { enabled: true, extends: "libexample", }, }
如果無法將副檔名與獨立的標頭檔案分開,
另一種方式是新增 #ifdef
守衛不過,
VNDK 擴充功能使用者新增定義標記。您可以定義
cc_defaults
:在 cflags
和連結中新增定義標記
與 shared_libs
共用程式庫。
例如,如要將新成員函式 Example2::get_b()
新增至
VNDK 擴充功能 libexample2_ext
,您必須修改現有的
標頭檔案,並新增 #ifdef
防護機制:
#ifndef LIBEXAMPLE2_EXAMPLE_H_ #define LIBEXAMPLE2_EXAMPLE_H_ class Example2 { public: Example2(); void get_a(); #ifdef LIBEXAMPLE2_ENABLE_VNDK_EXT void get_b(); #endif private: void *impl_; }; #endif // LIBEXAMPLE2_EXAMPLE_H_
名為 libexample2_ext_defaults
的 cc_defaults
已
為 libexample2_ext
的使用者定義:
cc_library { name: "libexample2", srcs: ["src/example2.cpp"], export_include_dirs: ["include"], vendor_available: true, vndk: { enabled: true, }, } cc_library { name: "libexample2_ext", srcs: ["src/example2.cpp"], export_include_dirs: ["include"], vendor: true, vndk: { enabled: true, extends: "libexample2", }, cflags: [ "-DLIBEXAMPLE2_ENABLE_VNDK_EXT=1", ], } cc_defaults { name: "libexample2_ext_defaults", shared_libs: [ "libexample2_ext", ], cflags: [ "-DLIBEXAMPLE2_ENABLE_VNDK_EXT=1", ], }
libexample2_ext
的使用者可能只需包括
defaults
的libexample2_ext_defaults
資源:
cc_binary { name: "example2_user_executable", defaults: ["libexample2_ext_defaults"], vendor: true, }
產品套件
在 Android 建構系統中,PRODUCT_PACKAGES
變數
會指明應當根據
安裝到裝置上。指定的指定依附元件
模組同樣也會自動安裝到裝置上
如果啟用 BOARD_VNDK_VERSION
,則含有
vendor_available
或vndk.enabled
可享特別優惠
治療方式,如果架構模組依附於含有
vendor_available
或 vndk.enabled
,核心變化版本
包含在遞移安裝組中。如果供應商模組
依附於包含 vendor_available
的模組,供應商變數會是
包含在遞移安裝組中。不過,模組的供應商變化版本
無論是否由供應商模組使用,vndk.enabled
都會安裝。
在建構系統看不到依附元件時 (例如共用程式庫)
通常可在執行階段中使用 dlopen()
開啟),因此您需要指定
PRODUCT_PACKAGES
中的模組名稱以安裝這些模組
。
如果模組有 vendor_available
或 vndk.enabled
模組名稱代表其核心變化版本。如要明確指定
PRODUCT_PACKAGES
中的供應商子類,附加 .vendor
新增至模組名稱。例如:
cc_library { name: "libexample", srcs: ["example.c"], vendor_available: true, }
在這個範例中,libexample
代表
/system/lib[64]/libexample.so
和 libexample.vendor
代表 /vendor/lib[64]/libexample.so
。如何安裝
/vendor/lib[64]/libexample.so
,新增libexample.vendor
至 PRODUCT_PACKAGES
:
PRODUCT_PACKAGES += libexample.vendor