リンカーとライブラリ

バージョンアップ共有オブジェクトの更新

共有オブジェクトに対する互換性のある変更は、内部バージョンアップによって吸収できます (「インタフェースの互換性」を参照)。すべての互換性のない変更では、新しい外部バージョンアップ名によって、新しい共有オブジェクトを作成する必要があります (「バージョンアップファイル名の管理」を参照)。

内部バージョンアップによって収容できる互換性のある更新は、次の 3 つの基本分類に属します。

最初の 2 つは、インタフェースバージョン定義に適切なシンボルを関連付けることによって実現されます。最後のカテゴリは、関連のシンボルを持たないウィークバージョン定義を作成することによって実現されます。

新しいシンボルの追加

新しい大域シンボルを含む、互換性のある、新しいリリースの共有オブジェクトは、これらのシンボルを新しいバージョン定義に割り当てる必要があります。この新しいバージョン定義は、以前のバージョン定義を継承しなければなりません。

次の mapfile の例では、新しいシンボル foo3 を新しいインタフェースバージョン定義 SUNW_1.2 に割り当てています。この新しいインタフェースは、元のインタフェース SUNW_1.1 を継承します。


$ cat mapfile
SUNW_1.2 {                   # Release X+1.
        global:
                foo3;
} SUNW_1.1;

SUNW_1.1 {                   # Release X.
        global:
                foo2;
                foo1;
        local:
                *;
};

バージョン定義の継承によって、共有オブジェクトのユーザーすべてに記録する必要があるバージョン情報の量が減ります。

内部実装の変更

オブジェクトの実装に対する更新からなる、互換性のある新しいリリースの共有オブジェクト (たとえばバグ修正や性能の改善) にはすべて、ウィークバージョン定義を付ける必要があります。この新しいバージョン定義は、更新の発生時に存在する最新のバージョン定義を継承しなければなりません。

次の mapfile の例では、ウィークバージョン定義 SUNW_1.1.1 を生成しています。この新しいインタフェースは、以前のインタフェース SUNW_1.1 によって提供された実装に対して、内部変更が加えられたことを示します。


$ cat mapfile
SUNW_1.1.1 { } SUNW_1.1;     # Release X+1.

SUNW_1.1 {                   # Release X.
        global:
                foo2;
                foo1;
        local:
                *;
};

新しいシンボルと内部実装の変更

同じリリースで内部変更と新しいシンボルの追加が同時に発生した場合は、ウィークバージョンとインタフェースバージョン定義の両方を作成する必要があります。次の例は、バージョン定義 SUNW_1.2 と、同じリリース期間中に追加されたインタフェース変更 SUNW_1.1.1 を示しています。どちらのインタフェースも元のインタフェース SUNW_1.1 を継承します。


$ cat mapfile
SUNW_1.2 {                   # Release X+1.
        global:
                foo3;
} SUNW_1.1;

SUNW_1.1.1 { } SUNW_1.1;     # Release X+1.

SUNW_1.1 {                   # Release X.
        global:
                foo2;
                foo1;
        local:
                *;
};

注 -

SUNW_1.1SUNW_1.1.1 の各バージョン定義へのコメントは、これらが両方とも同じリリースに適用されていることを示しています。


標準インタフェースへのシンボルの併合

場合によっては、ベンダーインタフェースによって提供されたシンボルが、新しい業界標準に組み込まれることがあります。新しい業界標準インタフェースを作成する場合、共有オブジェクトによって提供された元のインタフェース定義を維持することが重要です。これを実現するには、新しい標準インタフェースおよび元ののインタフェースの定義を構築できる、中間バージョン定義を作成する必要があります。

次の mapfile の例は、新しい業界標準インタフェース STAND.1 の追加を示しています。このインタフェースには、新しいシンボル foo4 と既存のシンボル foo3 および foo1 が含まれます。これらは当初、インタフェース SUNW_1.2 および SUNW_1.1 によって提供されたものです。


$ cat mapfile
STAND.1 {                    # Release X+2.
        global:
                foo4;
} STAND.0.1 STAND.0.2;

SUNW_1.2 {                   # Release X+1.
        global:
                SUNW_1.2;
} STAND.0.1 SUNW_1.1;

SUNW_1.1.1 { } SUNW_1.1;     # Release X+1.

SUNW_1.1 {                   # Release X.
        global:
                foo2;
        local:
                *;
} STAND.0.2;
                             # Subversion - providing for
STAND.0.1 {                  # SUNW_1.2 and STAND.1 interfaces.
        global:
                foo3;
};
                             # Subversion - providing for
STAND.0.2 {                  # SUNW_1.1 and STAND.1 interfaces.
        global:
                foo1;
};

ここで、シンボル foo3foo1 は、元のインタフェース定義および新しいインタフェース定義を作成するために使用される自身の中間インタフェース定義に取り込まれます。


注 -

SUNW_1.2 インタフェースの新しい定義は、各自のバージョン定義シンボルを参照しています。この参照がないと、SUNW_1.2 インタフェースには即時シンボル参照が含まれないため、ウィークバージョン定義として分類されます。


シンボル定義を標準インタフェースに併合する場合、元のインタフェース定義が引き続き同じシンボル列を表わすことが求められます。これは、pvs(1) を使用して検査できます。次の例は、SUNW_1.2 インタフェースがソフトウェアリリース X+1 に存在する場合のシンボル列を示しています。


$ pvs -ds -N SUNW_1.2 libfoo.so.1
        SUNW_1.2:
                foo3;
        SUNW_1.1:
                foo2;
                foo1;

ソフトウェアリリース X+2 での新しい標準インタフェースの導入によって、使用可能なインタフェースバージョン定義は変更されますが、元の各インタフェースによって提供されたシンボル列はそのままです。次の例は、インタフェース SUNW_1.2 が引き続きシンボル foo1foo2、および foo3 を提供することを示しています。


$ pvs -ds -N SUNW_1.2 libfoo.so.1
        SUNW_1.2:
        STAND.0.1:
                foo3;
        SUNW_1.1:
                foo2;
        STAND.0.2:
                foo1;

アプリケーションが、新しいサブバージョンの 1 つだけを参照する場合があります。この場合、以前のリリースでこのアプリケーションを実行しようとすると、実行時バージョンアップエラーが生じます (「バージョン定義への結合」を参照)。

この場合、アプリケーションバージョン結合は、既存のバージョン名を直接参照することによって昇格することができます (「追加バージョン定義への結合」を参照)。

たとえば、アプリケーションが、共有オブジェクト libfoo.so.1 からシンボル foo1 だけを参照する場合、そのバージョン参照は STAND.0.2 に対して行われます。このアプリケーションを以前のリリースで実行できるようにするには、バージョン制御 mapfile 指示を使用して、バージョン結合を SUNW_1.1 に昇格します。


$ cat prog.c
extern void foo1();

main()
{
        foo1();
}
$ cc -o prog prog.c -L. -R. -lfoo
$ pvs -r prog
        libfoo.so.1 (STAND.0.2);

$ cat mapfile
libfoo.so - SUNW_1.1 $ADDVERS=SUNW_1.1;
$ cc -M mapfile -o prog prog.c -L. -R. -lfoo
$ pvs -r prog
        libfoo.so.1 (SUNW_1.1);

新しい標準バイナリインタフェースの導入はめったになく、またほとんどのアプリケーションが多くのシンボルをインタフェースバージョンに関係なく参照するため、実際には、この方法でバージョン結合を行う必要はめったにありません。