必要な場面
次のような場合は、リンカー名前空間について理解しておく必要があります。 ネイティブコードを使用してアプリを構築する場合- VegaアプリでC/C++ライブラリを使用する
- サードパーティのネイティブSDK(ビデオプレーヤー、分析、DRM)を統合する
- ネイティブ実装のカスタムターボモジュールを作成する
- 既存のAndroidアプリまたはLinuxアプリをVegaに移植する
- 「library found in package」というエラーでビルドが失敗する
- 「cannot open shared object file」というエラーでアプリがクラッシュする
- 実行時にシンボルが適切に解決されない
- あるデバイスではアプリが動作するが、別のデバイスでは動作しない
- 認定の過程でアプリをABI検証に合格させる必要がある
- OSがアップデートされてもアプリが機能することを保証する必要がある
- ライブラリの競合による申請の却下を防ぎたい
リンカー名前空間が提供するもの
- 安定性: アプリは、バージョンが適切に管理されたアプリケーションバイナリインターフェイス(ABI)で安定しているシステムライブラリにのみアクセスします。
- 分離: バンドルされたライブラリがシステムライブラリと競合することはありません。
- 互換性: OSがアップデートされてもアプリは機能し続けます。
リンカー名前空間を使用して実現できること
- ネイティブコードを含むアプリを構築して、共有ライブラリを正しく使用できます。
- 競合を引き起こすことなくサードパーティライブラリをバンドルできます。
- システムライブラリを安全かつ効率的にリンクできます。
- ライブラリ依存関係やABI違反に関連するビルドエラーのトラブルシューティングを行うことができます。
動作のしくみ
動的リンカーは、ライブラリを2つの名前空間に分けることで、分離を強制して競合を防ぎます。 アプリの名前空間- Contains all libraries bundled in your app package (mounted, at runtime, to )
- Vega OSの公開ABIリストにある承認済みのシステムライブラリにアクセスできます。
- 内部のOSライブラリから分離されます。
- OS内部のライブラリが含まれます。
- 公開ABIリストにあるライブラリだけがアプリに公開されます。
- 不安定なシステムライブラリやバージョン互換性のないシステムライブラリへのアクセスを防ぎます。
実行時の読み込みプロセス
実行時に、アプリのネイティブエントリポイントがアプリ名前空間に読み込まれます。次に、その後に読み込まれるライブラリごとに、動的リンカーは次のことを行います。- リクエストされたライブラリが属する名前空間を決定します。
- アプリがそのライブラリにアクセスする権限を持っているかどうかを確認します。
- ライブラリがアプリの名前空間に属しているか、公開ABIリストに含まれている場合にのみライブラリを読み込みます。
- システム内部ライブラリへのアクセスをブロックし、互換性のないバージョンによるランタイムエラーを防ぎます。
システムライブラリへのアクセス
公開ABIリストにあるシステムライブラリは、最初にシステム名前空間に読み込まれますが、アプリからもシンボル解決を通じてアクセスすることができます。これは次のようなしくみで動作します。 例:アプリでlibpthread.so.0のpthread_createを使用する場合
- アプリのライブラリが
pthread_createをリクエストします。 - 動的リンカーが公開ABIリストから
libpthread.so.0を特定します。 - リンカーは、標準のシンボル解決を通じてシンボルをアプリで使用できるようにします。
- アプリは、システム名前空間に直接アクセスすることなく正常に
pthread_createを呼び出します。
libpthread.so.0自体が依存するライブラリ)は、それらも公開ABIリストに含まれていない限り、システム名前空間に分離されたままになります。
ライブラリの検索順序
Vegaの動的リンカーは、リクエストされたライブラリがOSの公開ABIの一部であるか、アプリにバンドルされているかによって、異なる検索パスを使用します。システムライブラリ(OSの公開ABIリストにある場合)
リクエストされたライブラリがOSの公開ABIリストに含まれている場合、リンカーは次の順序で検索します。/lib/:/usr/lib/:/vendor/usr/lib/(システムの優先検索パス)DT_RPATH(DT_RUNPATHが存在しない場合)LD_LIBRARY_PATHDT_RUNPATH- 残りのシステムのデフォルト検索パス
アプリにバンドルされたライブラリ(OSの公開ABIリストにない場合)
リクエストされたライブラリがOSの公開ABIリストに含まれていない場合、リンカーは次の順序で検索します。- /pkg/lib/<アーキテクチャ>/:/pkgs/:/mnt/(アプリの優先検索パス)
DT_RPATH(DT_RUNPATHが存在しない場合)LD_LIBRARY_PATHDT_RUNPATH- 残りのシステムのデフォルト検索パス
強制適用戦略
Vegaは2段階のアプローチでABIコンプライアンスを強制適用します。ビルド時の検証(ベストエフォート)
Vegaの開発ツールには、開発中の早い段階で問題を発見するためのベストエフォート型のビルド時ABI検証が含まれており、CIパイプラインでも実行できます。これにより、後の実行時の問題が回避されます。- 目的:デバイスをデプロイする前に潜在的なランタイムエラーを特定する
- スコープ:パッケージ構造と依存関係モデリングをABI要件と照らし合わせて検証します。
- 制限事項:動的な
dlopenパスや環境に依存するシンボルなど、考えられるすべての実行時シナリオを検出できるわけではありません。
実行時強制適用
動的リンカーは、アプリがVegaシステムイメージ内の物理デバイスまたは仮想デバイスで実行されるときに、名前空間の分離を厳密に適用します。アプリは非公開のシステムライブラリにはアクセスできず、システムがプロキシメカニズムを通じて公開するABIリストに登録されているライブラリにのみアクセスできます。パッケージの検証
SDKバージョン0.22以降では、ビルドプロセス中に自動的にABI検証が実行されます。Vegaパッケージングツール(vpt)は、パッケージに次の項目がないか確認します。- 動的にリンクする必要があるバンドルシステムライブラリ
- サードパーティの依存関係が見つからない
- ライブラリパスまたは読み込みパターンが正しくない
ビルドがABI違反で失敗する場合
ビルドがABI検証に失敗する場合は、次の手順を実行します。- パッケージから、Vega OSの公開ABIリストにあるシステムライブラリを削除します。
- ビルド構成(CMakeLists.txt、Makefile)を更新して、システムライブラリを動的にリンクします。
- システム以外の依存関係がすべてパッケージにバンドルされていることを確認します。
- VPKGを再ビルドし、再検証します。
- 実際のデバイスでテストして、実行時の動作を確認します。
ベストプラクティス
以下のベストプラクティスを活用することで、アプリがVegaのABI要件に準拠し、実行時の競合を回避できるようになります。システムライブラリはバンドルせずに動的にリンクする
ライブラリをバンドルする前に、必ずVega OSの公開ABIリストを確認してください。このリストに含まれているライブラリは、バンドルせずに動的にリンクします。 ビルド構成でDT_NEEDEDエントリを使用するか(推奨)、システムライブラリに対して明示的にdlopen()を呼び出します。
すべてのサードパーティ依存関係をバンドルする
Vega OSの公開ABIリストに含まれていないライブラリはすべて、アプリパッケージに直接追加します。 次の例では、libcurlをアプリにバンドルします。
非修飾のライブラリ名を使用する
dlopen()を呼び出すときは、パスを含まないライブラリ名を使用します。
明示的に依存関係をモデル化する
環境に依存するシンボルを使用しないでください。依存関係は必ずDT_NEEDEDエントリまたは明示的なdlopen()呼び出しによって宣言します。
これらのベストプラクティスに従うと、アプリは次のようなVegaの名前空間分離モデルの恩恵を受けます。
- 安全なバンドル:アプリでは、OSの公開ABIリストに含まれない任意のサードパーティライブラリを競合なくバンドルできます。
- シンボルの分離:アプリライブラリとシステムライブラリ間のシンボルの競合(不適切なバインドを含む)を防止できます。
- ABIの一貫性:それぞれの名前空間で、一貫した想定どおりのABIセマンティクスが維持されます。
- バージョン非依存性:アプリとシステムが、同じライブラリの異なるバージョンを干渉なく使用できます。

