リンカーとライブラリ

バージョン管理ファイル名の管理

リンク編集中に共有オブジェクトを入力するための最も一般的な手法は、-l オプションを使用する方法です。このオプションは、リンカーのライブラリ検索機構を使用して接頭辞 lib と接尾辞 .so が付いた共有オブジェクトを探します。

ただし、実行時に、共有オブジェクト依存関係は、そのバージョン管理ファイル名形式で存在していなければなりません。これらの命名規約に従う 2 つの異なる共有オブジェクトを維持するのではなく、2 つのファイル名間にファイルシステムリンクを作成します。

実行時共有オブジェクト libfoo.so.1 をコンパイル環境で使用できるようにするには、コンパイルファイル名から実行時ファイル名にシンボリックリンクを与えます。次に例を示します。


$ cc -o libfoo.so.1 -G -K pic foo.c
$ ln -s libfoo.so.1 libfoo.so
$ ls -l libfoo*
lrwxrwxrwx  1 usr grp          11 1991 libfoo.so -> libfoo.so.1
-rwxrwxr-x  1 usr grp        3136 1991 libfoo.so.1

シンボリックリンクまたはハードリンクを使用できます。ただし記述および診断目的としては、シンボリックリンクの方が有効です。

共有オブジェクト libfoo.so.1 は、実行時環境用に生成されています。シンボリックリンク libfoo.so の生成は、コンパイル環境でのこのファイルの使用も有効にしています。次に例を示します。


$ cc -o prog main.o -L. -lfoo

リンカーは、シンボリックリンク libfoo.so を追って見つける共有オブジェクト libfoo.so.1 によって記述されたインタフェースを使用して、再配置可能オブジェクト main.o を処理します。

一連のソフトウェアリリースにわたって、この共有オブジェクトの新しいバージョンごとにインタフェースを変更して配布できます。シンボリックリンクを変更することによって、適用可能なインタフェースを使用するよう、コンパイル環境を構築することができます。次に例を示します。


$ ls -l libfoo*
lrwxrwxrwx  1 usr grp          11 1993 libfoo.so -> libfoo.so.3
-rwxrwxr-x  1 usr grp        3136 1991 libfoo.so.1
-rwxrwxr-x  1 usr grp        3237 1992 libfoo.so.2
-rwxrwxr-x  1 usr grp        3554 1993 libfoo.so.3

共有オブジェクトの 3 つの主要バージョンが使用できます。これらの共有オブジェクトのうち、libfoo.so.1libfoo.so.2 の 2 つは、既存アプリケーションに対する依存関係を提供します。libfoo.so.3 は、新しいアプリケーションを作成して実行するための最新主要リリースを提供します。

このシンボリックリンク機構自体を使用するだけでは、コンパイル環境での使用から実行時環境での条件に合わせて共有オブジェクトを正しく結合することはできません。例が示しているように、リンカーは、動的実行可能ファイル prog に、それが処理した共有オブジェクトのファイル名を記録します。この場合、そのファイル名はコンパイル環境のファイル名です。


$ dump -Lv prog

prog:
 **** DYNAMIC SECTION INFORMATION ****
.dynamic:
[INDEX] Tag      Value
[1]     NEEDED   libfoo.so
.........

アプリケーション prog が実行されると、実行時リンカーは、依存関係 libfoo.so を検索します。prog は、このシンボリックリンクが指すすべてのファイルに結合されます。

依存関係として記録される正しい実行時名を指定するには、共有オブジェクト libfoo.so.1soname 定義によって構築する必要があります。この定義は、共有オブジェクトの実行時名を識別します。この名前は、この共有オブジェクトに対してリンクするすべてのオブジェクトによって、依存関係名として使用されます。この定義は、共有オブジェクト自体のリンク編集中に -h オプションを使用して与えることができます。次に例を示します。


$ cc -o libfoo.so.1 -G -K pic -h libfoo.so.1 foo.c
$ ln -s libfoo.so.1 libfoo.so
$ cc -o prog main.o -L. -lfoo
$ dump -Lv prog

prog:
 **** DYNAMIC SECTION INFORMATION ****
.dynamic:
[INDEX] Tag      Value
[1]     NEEDED   libfoo.so.1
.........

このシンボリックリンクと soname 機構は、コンパイル環境と実行時環境の共有オブジェクト命名規約の間に強固な同期を確立しました。 リンク編集中に処理されたインタフェースは、生成された出力ファイルに正確に記録されます。この記録によって、意図したインタフェースが実行時に提供されます。


注意 – 注意 –

外部的にバージョン管理された新しい共有オブジェクトを作成することは、大きな変更です。この共有オブジェクトを使用するすべてのプロセスの依存関係を完全に理解している必要があります。

たとえば、あるアプリケーションが、libfoo.so.1 および外部から記述されたオブジェクト libISV.so.1 と依存関係があるとします。この後者のオブジェクトは libfoo.so.1 とも依存関係があるとします。外部オブジェクト libISV.so.1 の使用には何の変更も加えずに、libfoo.so.2 内の新しいインタフェースを使用するためにアプリケーションを再設計すると、libfoo.so の主要なバージョンが両方とも実行プロセスに含まれることになります。libfoo.so のバージョンを変更する理由は互換性のない変更をマークすることだけなので、プロセス内にオブジェクトの両方のバージョンを持つことは、不正なシンボル結合が発生する原因となり、そのために望ましくない相互作用を引き起こすことがあります。