バージョン定義を含む共有オブジェクトに対して動的オブジェクトを構築する場合、リンカーに対して、特定のバージョン定義への結合を制限するように指示することができます。リンカーを使用すると、特定インタフェースへのオブジェクトの結合を効果的に制御することができます。
オブジェクトの結合条件は、ファイル制御命令によって制御できます。この命令は、リンカーの -M オプションと関連の mapfile を使用して提供されます。これらのファイル制御 mapfile 命令の構文は、次のとおりです。
name - version [ version ... ] [ $ADDVERS=version ]; |
Name - 共有オブジェクト依存関係の名前を表わす。この名前は、リンカーによって使用される共有オブジェクトのコンパイル環境名と一致しなければなりません (「ライブラリの命名規約」を参照)
Version - 結合に使用可能でなければならない共有オブジェクト内のバージョン定義名を表わす。複数のバージョン定義を指定できる
次のように、この結合制御が役立つシナリオがいくつかあります。
共有オブジェクトが、一意の依存しないバージョンを定義するようにバージョンアップされていて、異なる標準インタフェースを定義する可能性が高い場合、アプリケーションでは、その結合が特定インタフェースの条件を満たすように保証できる
共有オブジェクトがいくつかのソフトウェアリリースに対してバージョンアップされている場合、アプリケーション開発者は、前のソフトウェアリリースで使用可能であったインタフェースだけを使用するように制限できる。したがって、アプリケーションインタフェースの条件が共有オブジェクトの以前のリリースと一致するという知識を前提として、最新リリースの共有オブジェクトを使用してアプリケーションを構築することができる
次に、バージョン制御機構の使用例を示します。この例では、次のバージョンインタフェース定義を含む共有オブジェクト 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 libfoo.so - SUNW_1.1; |
たとえば、アプリケーション prog を開発する場合、アプリケーションが Release で実行されるようにすると、アプリケーションではそのリリースで使用可能なインタフェースだけを使用できます。アプリケーションがシンボル 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. No output written to prog
|
SUNW_1.1 インタフェースに準拠するには、bar への参照を削除する必要があります。これは、アプリケーションを再処理して bar に対する条件を削除するか、または bar の実装をアプリケーションの構築に追加することによって行います。
通常のオブジェクトシンボル結合からバージョン依存関係を作成するよりも、追加バージョン依存関係を記録した方がよい場合があります。これは、$ADDVERS ファイル制御命令を使用して実行できます。この節では、この追加結合が役に立ついくつかのシナリオについて説明します。
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 に対して単一の依存関係を持ちます。このことは、インタフェース foo1 が以前のリリースで存在したけれども、バージョン定義 STAND_A は存在しなかったために libfoo.so.1 が Release X+2 よりも小さいシステムでの prog の実行を阻害します。
したがって、アプリケーション prog は、次のファイル制御命令を使用して SUNW_1.1 に対する依存関係を作成することによって、その条件を以前のリリースに合わせて構築できます。
$ cat mapfile
libfoo.so - SUNW_1.1 $ADDVERS=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;
|
通常、アプリケーションは、この共有オブジェクトに対して構築されている場合、バージョン定義 SUNW_1.2.1 に対する弱い依存関係を記録します。この依存関係は情報提供だけを目的とするものであり、バージョン定義が実行時に使用される libfoo.so.1 に見つからなくても、アプリケーションを終了させません。
ファイル制御命令 $ADDVERS を使用すると、バージョン定義に対する明示的な依存関係を生成できます。この定義が弱い場合、この明示的参照によって、バージョン定義が強い依存関係に高められます。
したがって、アプリケーション prog は、次のファイル制御命令を使用して、SUNW_1.2.1 インタフェースを実行時に使用できるという条件を実施するように構築できます。
$ cat mapfile
libfoo.so - SUNW_1.1 $ADDVERS=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 が見つからないと、重大なエラーが生成されます。
1 つまたは 2 つの依存関係を処理する場合、バージョン定義への明示的な結合は、バージョン定義シンボルを参照することによっても達成できます。この処理は、リンカーの -u オプションを使用すると、最も簡単に実行できます。ただし、シンボル参照は非選択的であり、類似の名前を持つ複数のバージョン定義を含む可能性がある複数の依存関係を処理する場合は、この手法で明示的な結合を作成することはできません。