Android 8.1 以降では、ビルド システムに VNDK サポートが組み込まれています。 VNDK サポートが有効になっている場合、ビルド システムはモジュール間の依存関係をチェックし、ベンダー モジュールのベンダー固有のバリアントをビルドし、それらのモジュールを指定されたディレクトリに自動的にインストールします。
VNDK ビルド サポートの例
この例では、 Android.bp
モジュール定義はlibexample
という名前のライブラリを定義します。 vendor_available
プロパティは、フレームワーク モジュールとベンダー モジュールがlibexample
に依存する可能性があることを示します。
フレームワーク実行可能ファイル/system/bin/foo
とベンダー実行可能ファイル/vendor/bin/bar
どちらもlibexample
に依存しており、 shared_libs
プロパティにlibexample
があります。
libexample
フレームワーク モジュールとベンダー モジュールの両方で使用される場合、 libexample
の 2 つのバリアントがビルドされます。コア バリアント ( libexample
にちなんで命名) はフレームワーク モジュールによって使用され、ベンダー バリアント ( libexample.vendor
にちなんで命名) はベンダー モジュールによって使用されます。 2 つのバリアントは異なるディレクトリにインストールされます。
- コアバリアントは
/system/lib[64]/libexample.so
にインストールされます。 -
vndk.enabled
がtrue
であるため、ベンダー バリアントは VNDK APEX にインストールされます。
詳細については、 「モジュール定義」を参照してください。
ビルドサポートの構成
製品デバイスの完全なビルド システム サポートを有効にするには、 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
を使用して依存関係を (明示的に) 指定する必要があります。
VNDK アペックス
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}
から入手できます。
モジュール定義
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
を持つモジュールは、vendor:true
もvendor_available:true
も持たない非llndk_library
モジュールに依存します。
依存関係チェックは、 Android.bp
のheader_libs
、 static_libs
、およびshared_libs
、およびAndroid.mk
のLOCAL_HEADER_LIBRARIES
、 LOCAL_STATIC_LIBRARIES
、およびLOCAL_SHARED_LIBRARIES
に適用されます。
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 BOARD_VNDK_VERSION
有効な場合、これらのライブラリはこれらのライブラリとリンクします。シンボルは、次の場合にのみスタブ共有ライブラリに含まれます。
-
_PRIVATE
または_PLATFORM
で終わるセクションで定義されていない、 -
#platform-only
タグがありません。 -
#introduce*
タグがないか、タグがターゲットと一致します。
VNDK
Android.bp
ファイルでは、 cc_library
、 cc_library_static
、 cc_library_shared
、およびcc_library_headers
モジュール定義は、 vendor_available
、 vndk.enabled
、およびvndk.support_system_process
の 3 つの VNDK 関連プロパティをサポートします。
vendor_available
またはvndk.enabled
がtrue
の場合、2 つのバリアント ( coreとVendor ) がビルドされる可能性があります。コア バリアントはフレームワーク モジュールとして扱われ、ベンダー バリアントはベンダー モジュールとして扱われる必要があります。一部のフレームワーク モジュールがこのモジュールに依存している場合、コア バリアントがビルドされます。一部のベンダー モジュールがこのモジュールに依存している場合、ベンダー バリアントがビルドされます。ビルド システムは、次の依存関係チェックを強制します。
- コア バリアントは常にフレームワークのみであり、ベンダー モジュールにはアクセスできません。
- ベンダー バリアントには、フレームワーク モジュールは常にアクセスできません。
-
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}
) にインストールされます。
-
以下の表は、ビルド システムがベンダー バリアントをどのように処理するかをまとめたものです。
ベンダー_利用可能 | ヴンドク 有効 | ヴンドク サポートと同じプロセス | ベンダーバリアントの説明 |
---|---|---|---|
true | false | false | ベンダー バリアントはVND のみです。共有ライブラリは/vendor/lib[64] にインストールされます。 |
true | 無効(ビルドエラー) | ||
true | false | ベンダーのバリアントはVNDKです。共有ライブラリは VNDK APEX にインストールされます。 | |
true | ベンダーのバリアントはVNDK-SPです。共有ライブラリは VNDK APEX にインストールされます。 | ||
| | | ベンダーのバリエーションはありません。このモジュールはFWK のみです。 |
true | 無効(ビルドエラー) | ||
true | false | ベンダーのバリアントはVNDK-Privateです。共有ライブラリは VNDK APEX にインストールされます。これらをベンダー モジュールが直接使用してはなりません。 | |
true | ベンダーのバリアントはVNDK-SP-Privateです。共有ライブラリは VNDK APEX にインストールされます。これらをベンダー モジュールが直接使用してはなりません。 |
VNDK 拡張機能
VNDK 拡張機能は、追加の API を備えた VNDK 共有ライブラリです。拡張機能は/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 共有ライブラリ名 (または VNDK-SP 共有ライブラリ名) を指定する必要があります。 - VNDK 拡張機能 (または VNDK-SP 拡張機能) は、拡張元の基本モジュール名に基づいて名前が付けられます。たとえば、
libvndk_ext
の出力バイナリはlibvndk_ext.so
ではなくlibvndk.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 に依存している場合、モジュールは、 shared_libs
プロパティで VNDK 拡張機能の名前を指定する必要があります。
// 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)
条件付きコンパイル
このセクションでは、次の 3 つの VNDK 共有ライブラリ間の微妙な違い(バリアントの 1 つに対する機能の追加または削除など) に対処する方法について説明します。
- コアバリアント (例:
/system/lib[64]/libexample.so
) - ベンダーバリアント (例:
/apex/com.android.vndk.v${VER}/lib[64]/libexample.so
) - VNDK 拡張子 (例:
/vendor/lib[64]/vndk[-sp]/libexample.so
)
条件付きコンパイラフラグ
Android ビルド システムは、デフォルトでベンダー バリアントと VNDK 拡張機能の__ANDROID_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
で指定される場合があります。 target.vendor
で指定されたcflags
またはcppflags
、ベンダー バリアントに固有です。
たとえば、次の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
これら 2 つのファイルに従って、ビルド システムは次のエクスポートされたシンボルを含む共有ライブラリを生成します。
インストールパス | エクスポートされたシンボル |
---|---|
/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 ベンダー バリアントおよびVNDK 拡張機能の ABI を、 prebuilts/abi-dumps/vndk
にある参照 ABI ダンプと比較します。
- 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
に依存します。 fwk.c
はexclude_srcs
プロパティによって除外されているため、 libexample_cond_exclude
のベンダー バリアントには、 both.c
のコードのみが含まれます。同様に、 libfwk_only
exclude_shared_libs
プロパティによって除外されているため、共有ライブラリlibboth
のみに依存します。
VNDK 拡張機能からヘッダーをエクスポートする
VNDK 拡張機能により、新しいクラスまたは新しい関数が VNDK 共有ライブラリに追加される場合があります。これらの宣言を独立したヘッダーに保持し、既存のヘッダーを変更しないようにすることをお勧めします。
たとえば、新しいヘッダー ファイルinclude-ext/example/ext/feature_name.h
VNDK 拡張機能libexample_ext
に対して作成されます。
- Android.bp
- include-ext/example/ext/feature_name.h
- include/example/example.h
- src/example.c
- src/ext/機能名.c
次のAndroid.bp
では、 libexample
include
のみをエクスポートしますが、 libexample_ext
include
とinclude-ext
両方をエクスポートします。これにより、 libexample
のユーザーがfeature_name.h
誤ってインクルードすることがなくなります。
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