リンカー名前空間によるネイティブライブラリの管理
リンカー名前空間とは、プロセス内で共有ライブラリを別々のリンク環境に分けて編成する、ライブラリの分離テクニックです。Vegaの動的リンカー(ld-linux-<アーキテクチャ>.so)は、アプリのライブラリとシステムライブラリ間の競合を防ぐために、このテクニックを実装しています。動的リンカーは、実行時にすべてのデバイスに名前空間の境界を適用します。リンカー名前空間は、Vega OS上で実行されるすべてのネイティブコードに適用されます。
必要な場面
次のような場合は、リンカー名前空間について理解しておく必要があります。
ネイティブコードを使用してアプリを構築する場合
- VegaアプリでC/C++ライブラリを使用する
- サードパーティのネイティブSDK(ビデオプレーヤー、分析、DRM)を統合する
- ネイティブ実装のカスタムターボモジュールを作成する
- 既存のAndroidアプリまたはLinuxアプリをVegaに移植する
ビルドまたは実行時に問題が発生した場合
- 「library found in package」というエラーでビルドが失敗する
- 「cannot open shared object file」というエラーでアプリがクラッシュする
- 実行時にシンボルが適切に解決されない
- あるデバイスではアプリが動作するが、別のデバイスでは動作しない
Amazonアプリストアへの申請を準備する場合
- 認定の過程でアプリをABI検証に合格させる必要がある
- OSがアップデートされてもアプリが機能することを保証する必要がある
- ライブラリの競合による申請の却下を防ぎたい
リンカー名前空間が提供するもの
- 安定性: アプリは、バージョンが適切に管理されたアプリケーションバイナリインターフェイス(ABI)で安定しているシステムライブラリにのみアクセスします。
- 分離: バンドルされたライブラリがシステムライブラリと競合することはありません。
- 互換性: OSがアップデートされてもアプリは機能し続けます。
リンカー名前空間を使用して実現できること
- ネイティブコードを含むアプリを構築して、共有ライブラリを正しく使用できます。
- 競合を引き起こすことなくサードパーティライブラリをバンドルできます。
- システムライブラリを安全かつ効率的にリンクできます。
- ライブラリ依存関係やABI違反に関連するビルドエラーのトラブルシューティングを行うことができます。
動作のしくみ
動的リンカーは、ライブラリを2つの名前空間に分けることで、分離を強制して競合を防ぎます。
アプリの名前空間
- アプリパッケージにバンドルされているすべてのライブラリが含まれます(実行時に
/pkg/lib/<アーキテクチャ>/、/pkgs/、/mnt/にマウントされます)。 - Vega OSの公開ABIリストにある承認済みのシステムライブラリにアクセスできます。
- 内部のOSライブラリから分離されます。
システム名前空間
- OS内部のライブラリが含まれます。
- 公開ABIリストにあるライブラリだけがアプリに公開されます。
- 不安定なシステムライブラリやバージョン互換性のないシステムライブラリへのアクセスを防ぎます。
実行時の読み込みプロセス
実行時に、アプリのネイティブエントリポイントがアプリ名前空間に読み込まれます。次に、その後に読み込まれるライブラリごとに、動的リンカーは次のことを行います。
- リクエストされたライブラリが属する名前空間を決定します。
- アプリがそのライブラリにアクセスする権限を持っているかどうかを確認します。
- ライブラリがアプリの名前空間に属しているか、公開ABIリストに含まれている場合にのみライブラリを読み込みます。
- システム内部ライブラリへのアクセスをブロックし、互換性のないバージョンによるランタイムエラーを防ぎます。
システムライブラリへのアクセス
公開ABIリストにあるシステムライブラリは、最初にシステム名前空間に読み込まれますが、アプリはシンボル解決を通じて、引き続きシステムライブラリにアクセスできます。その方法は次のとおりです。
例: アプリでlibpthread.so.0のpthread_createを使用する場合
- アプリのライブラリが
pthread_createをリクエストします。 - 動的リンカーが公開ABIリストから
libpthread.so.0を特定します。 - リンカーは、標準のシンボル解決によって、アプリでシンボルを使用できるようにします。
- アプリは、システム名前空間に直接アクセスしなくても、
pthread_createを正しく呼び出します。
このメカニズムにより、名前空間を分離したままで、アプリはバージョン管理され安定したAPIにのみアクセスできます。これらのシステムライブラリの推移的依存関係(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()を呼び出します。
# CMakeLists.txtで、target_link_librariesにシステムライブラリを追加します
# これにより、動的リンク用のDT_NEEDEDエントリが作成されます
target_link_libraries(your_app PRIVATE pthread)
すべてのサードパーティ依存関係をバンドルする
Vega OSの公開ABIリストに含まれていないライブラリはすべて、アプリパッケージに直接追加します。
次の例では、libcurlをアプリにバンドルします。
# CMakeLists.txt内:
# 1.ビルド環境でライブラリを検索します
find_library(CURL_LIBRARY curl)
# 2.ライブラリをターゲットにリンクします
target_link_libraries(your_app PRIVATE ${CURL_LIBRARY})
# 3.ライブラリをパッケージのlibディレクトリにインストールします
install(FILES ${CURL_LIBRARY} DESTINATION lib)
非修飾のライブラリ名を使用する
dlopen()を呼び出すときは、パスを含まないライブラリ名を使用します。
// 正しい例
dlopen("libutil.so.1", RTLD_NOW);
// 間違った例:完全修飾パスは使用しないでください
dlopen("/some/path/libutil.so.1", RTLD_NOW);
明示的に依存関係をモデル化する
環境に依存するシンボルを使用しないでください。依存関係は必ずDT_NEEDEDエントリまたは明示的なdlopen()呼び出しによって宣言します。
これらのベストプラクティスに従うと、アプリは次のようなVegaの名前空間分離モデルの恩恵を受けます。
- 安全なバンドル: アプリでは、OSの公開ABIリストに含まれない任意のサードパーティライブラリを競合なくバンドルできます。
- シンボルの分離: アプリライブラリとシステムライブラリ間のシンボルの競合(不適切なバインドを含む)を防止できます。
- ABIの一貫性: それぞれの名前空間で、一貫した想定どおりのABIセマンティクスが維持されます。
- バージョン非依存性: アプリとシステムが、同じライブラリの異なるバージョンを干渉なく使用できます。
Vega OS公開ABIリスト
以下のライブラリは、公開ABIを通じてすべてのアプリで利用できます。
| ライブラリ | 説明 |
|---|---|
| ld-linux-<アーキテクチャ>.so | 動的リンカー |
| libc.so.6 | Glibc v2.35 |
| libdl.so.2 | Glibc v2.35 |
| libm.so.6 | Glibc v2.35 |
| libpthread.so.0 | Glibc v2.35 |
| librt.so.1 | Glibc v2.35 |
| libutil.so.1 | Glibc v2.35 |
| libkeplerscript-2.so.2 | カスタムターボモジュールをサポートするために使用 |
| libkeplerscript-3.so.3 | カスタムターボモジュールをサポートするために使用 |
| libapmf.so | ネイティブIDLをサポートするために使用 |
関連トピック
Last updated: 2026年6月18日

