リンカーとライブラリ

命名規約

リンカーも実行時リンカーも、ファイル名によってファイルを解釈しません。ファイルはすべて検査されて、その 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 は付けた方が望ましく、一連のソフトウェアリリースで共有オブジェクトの正しい結合を行うためにはバージョン番号も必要です。バージョン番号の付け方については、第 5 章「アプリケーションバイナリインタフェースとバージョン管理」を参照してください。


注 –

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


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

動的実行可能ファイルまたは共有オブジェクトでの依存関係の記録は、デフォルトでは、関連する共有オブジェクトがリンカーによって参照されるときのファイル名になります。たとえば、次の動的実行可能ファイルは、同じ共有オブジェクト 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 オプションを使用すると、その実行時名を共有オブジェクト自体に記録できます。次の例では、共有オブジェクトの実行時名 libfoo.so.1 は、ファイル自体に記録されます。この識別名は、soname と呼ばれます。


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

次の例は、dump(1) を使用して SONAME タグを持つエントリを参照し、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: recording name conflict: file `./libfoo.so' and \
    file `./libbar.so' provide identical dependency names: libsame.so.1
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: recording name conflict: file `./libfoo.so' and \
    -h option provide identical dependency names: libsame.so.1
ld: fatal: File processing errors. No output written to libbar.so