リンカーとライブラリ

命名規約

リンカーも実行時リンカーも、ファイル名によってファイルを解釈しません。ファイルはすべて検査されて、その ELF タイプが判定されます (「ELF ヘッダー」を参照)。この情報から、ファイルの処理条件が推定されます。ただし、共有オブジェクトは通常、コンパイル環境または実行時環境のどちらの一部として使用されるかによって、2 つの命名規約のうちどちらかに従います。

共有オブジェクトは、コンパイル環境の一部として使用される場合、リンカーによって読み取られて処理されます。これらの共有オブジェクトは、リンカーに渡されるコマンド行の一部で明示的なファイル名によって指定できますが、リンカーのライブラリ検索機能を利用するために -l オプションを使用する方が一般的です (「共有オブジェクトの処理」を参照)。

共有オブジェクトをこのリンカー処理に使用できるようにするには、接頭辞 lib と接尾辞 .so によって共有オブジェクトを指定する必要があります。たとえば、/usr/lib/libc.so は、コンパイル環境に使用できる標準 C ライブラリの共有オブジェクト表現です。規則によって、64 ビットの共有オブジェクトは、64 と呼ばれる lib ディレクトリのサブディレクトリに置かれます。たとえば、/usr/lib/libc.so.1 がある場合、64 ビットに対応するオブジェクトは、/usr/lib/64/libc.so.1 にあります。

共有オブジェクトは、実行時環境の一部として使用される場合、実行時リンカーによって読み取られて処理されます。一連のソフトウェアリリースでは、共有オブジェクトのエクスポートされたインタフェースでの変更が可能でなければならない場合があります。このインタフェースの変更は、バージョンアップされたファイル名として共有オブジェクトを提供することによって予測可能にして、サポートできます。

バージョン付きファイル名は、通常、.so 接尾辞の後にバージョン番号が続くという形式をとります。たとえば、/usr/lib/libc.so.1 は、実行時環境で使用可能な標準 C ライブラリのバージョン 1 の共有オブジェクト表示です。

共有オブジェクトが、コンパイル環境内での使用をまったく目的としていない場合は、従来の lib 接頭辞がその名前から削除されることがあります。このカテゴリに属する共有オブジェクトの例には、dlopen(3DL) だけに使用されるオブジェクトがあります。実際のファイルタイプを示すために、接尾辞 .so は付けた方が望ましく、一連のソフトウェアリリースで共有オブジェクトの正しい結合を行うためにはバージョン番号も必要です。


注 -

dlopen(3DL) で使用される共有オブジェクト名は通常、単純ファイル名として表わされます。つまり、名前に `/' が付きません。この規則によって、実行時リンカーは、実際のファイルを検索するための規則を自由に使用できます (詳細は、「追加オブジェクトの読み込み」を参照)。


第 5 章「バージョンアップ」では、一連のソフトウェアリリースで共有オブジェクトインタフェースのバージョンアップという概念についてさらに詳しく説明します。また、コンパイル環境と実行時環境の両方で使用される共有オブジェクト間の命名規約を調整するためのメカニズムについても説明します。ただし最初に、共有オブジェクトが各自の実行時名を記録するためのメカニズムを説明しておきます。

共有オブジェクト名の記録

動的実行可能ファイルまたは共有オブジェクトでの「依存関係」の記録は、デフォルトでは、関連する共有オブジェクトがリンカーによって参照されるときのファイル名になります。たとえば、次の動的実行可能ファイルは、同じ共有オブジェクト libfoo.so に対して構築されますが、同じ依存関係の解釈は異なります。


$ cc -o ../tmp/libfoo.so -G foo.o
$ cc -o prog main.o -L../tmp -lfoo
$ dump -Lv prog | grep NEEDED
[1]     NEEDED   libfoo.so

$ cc -o prog main.o ../tmp/libfoo.so
$ dump -Lv prog | grep NEEDED
[1]     NEEDED   ../tmp/libfoo.so

$ cc -o prog main.o /usr/tmp/libfoo.so
$ dump -Lv prog | grep NEEDED
[1]     NEEDED   /usr/tmp/libfoo.so

上記の例が示すように、依存関係を記録するこのメカニズムでは、コンパイル手法の違いによって不一致が生じる可能性があります。また、リンク編集中に参照される共有オブジェクトの位置が、インストールされたシステムでの共有オブジェクトの最終的な位置と異なる場合があります。

依存関係を指定するより一貫した手法として、共有オブジェクトは、それぞれの内部にファイル名を記録できます。共有オブジェクトは、このファイル名によって実行時に参照されます。

共有オブジェクトのリンク編集中、-h オプションを使用すると、その実行時名を共有オブジェクト自体に記録できます。次に例を示します。


$ cc -o ../tmp/libfoo.so -G -K pic -h libfoo.so.1 foo.c 

ここで、共有オブジェクトの実行時名 libfoo.so.1 は、ファイル自体に記録されます。この識別名は soname と呼ばれ、その記録は dump(1) を使用し、SONAME タグを持つエントリを参照して表示できます。次に例を示します。


$ dump -Lvp ../tmp/libfoo.so

../tmp/libfoo.so:
[INDEX] Tag      Value
[1]     SONAME   libfoo.so.1
.........

リンカーが soname を含む共有オブジェクトを処理する場合、生成中の出力ファイル内に依存関係として記録されるのはこの名前です。

したがって、前の例から動的実行可能ファイル prog を作成しているときに、この新しいバージョンの libfoo.so が使用されると、実行可能ファイルを作成するための 3 つの方式すべてによって同じ依存関係が記録されます。


$ cc -o prog main.o -L../tmp -lfoo
$ dump -Lv prog | grep NEEDED
[1]     NEEDED   libfoo.so.1

$ cc -o prog main.o ../tmp/libfoo.so
$ dump -Lv prog | grep NEEDED
[1]     NEEDED   libfoo.so.1

$ cc -o prog main.o /usr/tmp/libfoo.so
$ dump -Lv prog | grep NEEDED
[1]     NEEDED   libfoo.so.1

上記の例では、-h オプションは、単純 (simple) ファイル名を指定するために使用されます。つまり、名前に `/' が付きません。この規則では、実行時リンカーが実際のファイルを検索するための規則を自由に使用できるため、これを使用することをお勧めします (詳細は、「共有オブジェクトの依存関係の配置」を参照)。

アーカイブへの共有オブジェクトの取り込み

共有オブジェクトに soname を記録するメカニズムは、共有オブジェクトがアーカイブライブラリから処理される場合に重要です。

アーカイブは、1 つまたは複数の共有オブジェクトから構築し、動的実行可能ファイルまたは共有オブジェクトを生成するために使用できます。共有オブジェクトは、リンク編集の条件を満たすためにアーカイブから抽出できます (アーカイブ抽出条件の詳細は、「アーカイブ処理」を参照)。ただし、作成中の出力ファイルに連結される再配置可能オブジェクトの処理とは違って、アーカイブから抽出された共有オブジェクトは、すべて依存関係として記録されます。

アーカイブ構成要素の名前はリンカーによって構築されて、アーカイブ名とアーカイブ内のオブジェクトの連結になります。次に例を示します。


$ cc -o libfoo.so.1 -G -K pic foo.c
$ ar -r libfoo.a libfoo.so.1
$ cc -o main main.o libfoo.a
$ dump -Lv main | grep NEEDED
[1]     NEEDED   libfoo.a(libfoo.so.1)

この連結名を持つファイルが実行時に存在することはほとんどないため、共有オブジェクト内に soname を与える方法が、依存関係の有意な実行時ファイル名を生成する唯一の手段です。


注 -

実行時リンカーは、アーカイブからオブジェクトを抽出しません。したがって、上記の例では、必要な共有オブジェクト依存関係をアーカイブから抽出して、実行時環境で使用できるようにする必要があります。


記録名の衝突

共有オブジェクトが実行可能ファイルまたは別の共有オブジェクトを作成するために使用される場合、リンカーは、いくつかの整合性検査を実行して、出力ファイル内に記録される依存関係名すべてが一意になるように保証します。

依存関係名の衝突は、リンク編集への入力ファイルとして使用される 2 つの共有オブジェクトがどちらも同じ soname を含む場合に発生する可能性があります。次に例を示します。


$ cc -o libfoo.so -G -K pic -h libsame.so.1 foo.c
$ cc -o libbar.so -G -K pic -h libsame.so.1 bar.c
$ cc -o prog main.o -L. -lfoo -lbar
ld: fatal: file ./libbar.so: recording name `libsame.so.1' ¥
           matches that provided by file ./libfoo.so
ld: fatal: File processing errors. No output written to prog

記録された soname を持たない共有オブジェクトのファイル名が、同じリンク編集中に使用された別の共有オブジェクトの soname に一致する場合にも同様にエラー条件が発生します。

生成中の共有オブジェクトの実行時名が、その依存関係の 1 つに一致する場合にも、リンカーは名前の衝突を報告します。次に例を示します。


$ cc -o libbar.so -G -K pic -h libsame.so.1 bar.c -L. -lfoo
ld: fatal: file ./libfoo.so: recording name `libsame.so.1'  ¥
           matches that supplied with -h option
ld: fatal: File processing errors. No output written to libbar.so