バージョン定義を含む共有オブジェクトに対してリンクされた動的オブジェクトを作成する場合、特定のバージョン定義に対する結合を制限するように、リンカーに指示できます。リンカーを使用すると、特定インタフェースへのオブジェクトの結合を効果的に制御することができます。
オブジェクトの結合要件は DEPEND_VERSIONS mapfile 指令で制御できます。この指令は、リンカーの –M オプションと関連の mapfile を使用して提供されます。DEPEND_VERSIONS 指令は次の構文を使用します。
$mapfile_version 2 DEPEND_VERSIONS objname { ALLOW = version_name; REQUIRE = version_name; .... };
objname は共有オブジェクトの依存関係の名前を表します。この名前は、リンカーによって使用される共有オブジェクトのコンパイル環境名と一致しなければなりません。ライブラリの命名規約を 参照してください。
ALLOW 属性を使用して、結合に利用できるようにすべき共有オブジェクト内のバージョン定義名を指定します。複数の ALLOW 属性を指定できます。
REQUIRE 属性を使用すると、記録されるバージョン定義を追加できます。複数の REQUIRE 属性を指定できます。
バージョン結合の制御は、次のような場合に役立ちます。
共有オブジェクトが一意の独立したバージョンを定義するとき。このバージョン管理は、異なる標準インタフェースを定義するときに使用できます。結合制御でオブジェクトを構築することによって、そのオブジェクトが特定のインタフェースだけに結合することを保証できます。
複数世代のソフトウェアリリースにまたがって、共有オブジェクトをバージョン管理するとき。結合制御でオブジェクトを構築することによって、以前のソフトウェアリリースで利用可能だったインタフェースだけに結合するように制限できます。したがって、最新リリースの共有オブジェクトを使用して構築したオブジェクトでも、古いリリースの共有オブジェクトを使用して実行できます。
次に、バージョン制御メカニズムの使用例を示します。この例では、次のバージョンインタフェース定義を含む共有オブジェクト libfoo.so.1 を使用しています。
$ pvs -dsv libfoo.so.1 libfoo.so.1: _end; _GLOBAL_OFFSET_TABLE_; _DYNAMIC; _edata; _PROCEDURE_LINKAGE_TABLE_; _etext; SUNW_1.1: foo1; foo2; SUNW_1.1; SUNW_1.2: {SUNW_1.1}: bar;
バージョン定義 SUNW_1.1 および SUNW_1.2 は、ソフトウェア Release X および Release X+1 で使用可能な libfoo.so.1 内のインタフェースをそれぞれ表します。
アプリケーションは、次のバージョン制御 mapfile 指令を使用して、Release X で使用可能なインタフェースだけに結合するように構築できます。
$ cat mapfile $mapfile_version 2 DEPEND_VERSIONS libfoo.so { ALLOW = SUNW_1.1; }
たとえば、Release X 上で動作するアプリケーション prog を開発するとします。アプリケーションでは、Release X で使用可能なインタフェース以外は使用できません。シンボル bar を間違えて参照すると、アプリケーションは要求されるインタフェースに準拠しなくなります。リンカーはこの状態を未定義のシンボルエラーとして通知します。
$ cat prog.c extern void foo1(); extern void bar(); main() { foo1(); bar(); } $ cc -o prog prog.c -M mapfile -L. -R. -lfoo Undefined first referenced symbol in file bar prog.o (symbol belongs to unavailable \ version ./libfoo.so (SUNW_1.2)) ld: fatal: symbol referencing errors
SUNW_1.1 インタフェースに準拠するには、bar への参照を削除する必要があります。これは、アプリケーションを再処理して bar に対する要件を削除するか、または bar の実装をアプリケーションの作成に追加することによって行います。
オブジェクトの標準のシンボル結合から作成されるバージョン依存関係よりも多くのバージョン依存関係を記録するには、DEPEND_VERSIONS mapfile 指令に REQUIRE 属性を使用します。次のセクションでは、この追加結合が役に立ついくつかのシナリオについて説明します。
1 つのシナリオは、ISV 固有のインタフェースを公開標準インタフェースで使用します。
libfoo.so.1 の例に続いて、Release X+2 において、バージョン定義 SUNW_1.1 が 2 つの標準リリース STAND_A と STAND_B に分割される場合を想定します。互換性を維持するには、SUNW_1.1 バージョン定義を維持する必要があります。次の例では、このバージョン定義は 2 つの標準定義を継承するものとして表されています。
$ pvs -dsv libfoo.so.1 libfoo.so.1: _end; _GLOBAL_OFFSET_TABLE_; _DYNAMIC; _edata; _PROCEDURE_LINKAGE_TABLE_; _etext; SUNW_1.1: {STAND_A, STAND_B}: SUNW_1.1; SUNW_1.2: {SUNW_1.1}: bar; STAND_A: foo1; STAND_A; STAND_B: foo2; STAND_B;
アプリケーション prog の唯一の要件がインタフェースシンボル foo1 である場合、このアプリケーションはバージョン定義 STAND_A に対して単一の依存関係を持ちます。このことは、libfoo.so.1 が Release X+2 よりも小さいシステムでの prog の実行を阻害します。以前のリリースでは、インタフェース foo1 が存在する場合でも、バージョン定義 STAND_A は存在しませんでした。
アプリケーション prog は、SUNW_1.1 に対する依存関係を作成することによって、その要件を以前のリリースに合わせて構築できます。
$ cat mapfile $mapfile_version 2 DEPEND_VERSIONS libfoo.so { ALLOW = SUNW_1.1; REQUIRE = SUNW_1.1; }; $ cat prog extern void foo1(); main() { foo1(); } $ cc -M mapfile -o prog prog.c -L. -R. -lfoo $ pvs -r prog libfoo.so.1 (SUNW_1.1);
この明示的な依存関係は、真の依存関係の要件をカプセル化するのに十分です。この依存関係は古いリリースとの互換性も保ちます。
ウィークバージョン定義の作成では、ウィークバージョン定義を使用して、内部実装の変更をマークする方法について説明しました。これらのバージョン定義は、オブジェクトに対して行われたバグ修正と性能の改善に適しています。ウィークバージョンの存在が必要である場合、ウィークバージョン定義への明示的な依存関係を作成できます。オブジェクトを正しく機能させるためにバグ修正や性能の改善が重要な場合、このような依存関係の作成も重要になります。
上記の libfoo.so.1 の例で、バグ修正がウィークバージョン定義 SUNW_1.2.1 としてソフトウェア Release X+3 に組み込まれている場合を想定します。
$ pvs -dsv libfoo.so.1 libfoo.so.1: _end; _GLOBAL_OFFSET_TABLE_; _DYNAMIC; _edata; _PROCEDURE_LINKAGE_TABLE_; _etext; SUNW_1.1: {STAND_A, STAND_B}: SUNW_1.1; SUNW_1.2: {SUNW_1.1}: bar; STAND_A: foo1; STAND_A; STAND_B: foo2; STAND_B; SUNW_1.2.1 [WEAK]: {SUNW_1.2}: SUNW_1.2.1;
通常、アプリケーションは、この libfoo.so.1 に対して構築されている場合、バージョン定義 SUNW_1.2.1 に対する弱い依存関係を記録します。この依存関係は情報提供だけを目的とします。実行時に使用される libfoo.so.1 の実装にバージョン定義が見つからなくても、この依存関係によってアプリケーションが強制終了されることはありません。
REQUIRE 属性を DEPEND_VERSIONS mapfile 指令に使用すると、バージョン定義に明示的な依存関係を生成できます。この定義がウィークである場合、この明示的参照によって、バージョン定義が強い依存関係に高められます。
アプリケーション prog は、次のファイル制御指令を使用して、SUNW_1.2.1 インタフェースを実行時に使用できるという要件を実施するように構築できます。
$ cat mapfile $mapfile_version 2 DEPEND_VERSIONS libfoo.so { ALLOW = SUNW_1.1; REQUIRE = SUNW_1.2.1; }; $ cat prog extern void foo1(); main() { foo1(); } $ cc -M mapfile -o prog prog.c -L. -R. -lfoo $ pvs -r prog libfoo.so.1 (SUNW_1.2.1);
prog には、インタフェース STAND_A に対する明示的な依存関係があります。バージョン定義 SUNW_1.2.1 は、強いバージョンに高められているため、依存関係 STAND_A によって正規化されます。実行時にバージョン定義 SUNW_1.2.1 が見つからないと、重大なエラーが生成されます。