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 の 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/includeframeworks/native/includeframeworks/native/opengl/includehardware/libhardware/includehardware/libhardware_legacy/includehardware/ril/includelibnativehelper/includelibnativehelper/include_deprecatedsystem/core/includesystem/media/audio/include
モジュールがこれらのディレクトリのヘッダーに依存している場合は、header_libs、static_libs、または shared_libs で依存関係を(明示的に)指定する必要があります。
VNDK APEX
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 ファイルでは、ベンダー モジュールは、vendor プロパティまたは proprietary プロパティを 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 が有効になると、ベンダー モジュールはこれらのライブラリとリンクします。次のような場合のみ、シンボルがスタブ共有ライブラリに含まれます。
- セクションの末尾に
_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 つのバリアント(コアとベンダー)をビルドされることがあります。コアバリアントはフレームワーク モジュールとして、ベンダー バリアントはベンダー モジュールとして処理します。一部のフレームワーク モジュールがこのモジュールに依存している場合、コアバリアントがビルドされます。一部のベンダー モジュールがこのモジュールに依存している場合、ベンダー バリアントがビルドされます。ビルドシステムは、以下の依存関係をチェックします。
- コアバリアントは常にフレームワークのみであり、ベンダー モジュールからはアクセスできない。
- ベンダー バリアントは、フレームワーク モジュールからは常にアクセスできない。
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})にインストールされる。
下記の表に、ビルドシステムがベンダー バリアントをどのように処理するかをまとめます。
| vendor_available | vndk の有効化 |
vndk support_system_process |
ベンダー バリアントの説明 |
|---|---|---|---|
true |
false |
false |
ベンダー バリアントは VND-ONLY です。共有ライブラリは /vendor/lib[64] にインストールされます。 |
true |
無効(ビルドエラー) | ||
true |
false |
ベンダー バリアントは VNDK です。共有ライブラリは VNDK APEX にインストールされます。 | |
true |
ベンダー バリアントは VNDK-SP です。共有ライブラリは VNDK APEX にインストールされます。 | ||
|
|
|
ベンダー バリアントはありません。このモジュールは FWK-ONLY です。 |
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 に依存しています。libexample_cond_exclude のベンダー バリアントでは、fwk.c が exclude_srcs プロパティにより除外されているため、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/feature_name.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