通常、コンパイラドライバによって、適切なライブラリがリンカーに指定されているかどうかが確認されますが、ほとんどの場合、自分独自のライブラリを指定することが必要です。共有オブジェクトとアーカイブは、リンカーに対して必要な入力ファイルの名前を明示的につけることで指定できます。ただし、より一般的で柔軟性が高いのは、リンカーの –l オプションを使用する方法です。
規約により、共有オブジェクトは通常、接頭辞 lib と接尾辞 .so によって指定されます。アーカイブは、接頭辞 lib と接尾辞 .a によって指定されます。たとえば、libfoo.so は、コンパイル環境に使用できる foo 実装の共有オブジェクトバージョンです。libfoo.a は、ライブラリのアーカイブバージョンです。
これらの規則は、リンカーの –l オプションによって認識されます。このオプションは、通常、追加ライブラリをリンク編集に供給する場合に使用します。次の例では、リンカーに libfoo.so を検索するように指示します。リンカーが libfoo.so を検索できない場合は、libfoo.a を検索してから次の検索ディレクトリに移動します。
$ cc -o prog file1.c file2.c -lfoo
動的モードでリンク編集を行う場合、共有オブジェクトとアーカイブとを組み合わせたものへのリンクを選択できます。静的モードでリンク編集を行う場合、入力を受け入れるのはアーカイブライブラリだけです。
動的モードで –l オプションを使用する場合、リンカーはまず指定された名前と一致する共有オブジェクトの指定ディレクトリを検索します。一致するものが見つからない場合、リンカーは、次に同じディレクトリ内でアーカイブライブラリを検索します。静的モードで –l オプションを使用する場合は、アーカイブライブラリだけが検索されます。
ライブラリ検索メカニズムにより動的モードで共有オブジェクトを検索する場合、指定したディレクトリがまず検索され、次にアーカイブライブラリが検索されます。検索タイプをより詳細に制御するには、–B オプションを使用します。
コマンド行に –B dynamic オプション、–B static オプションを指定することによって、ライブラリの検索対象をそれぞれ共有オブジェクト、アーカイブに切り替えることができます。たとえば、アプリケーションをアーカイブ libfoo.a と共有オブジェクト libbar.so にリンクするには、次のコマンドを発行します。
$ cc -o prog main.o file1.c -Bstatic -lfoo -Bdynamic -lbar
オプション –B static と –B dynamic は、正確には対称ではありません。–B static を指定すると、リンカーは、次の–B dynamic の発生まで入力として共有オブジェクトを受け入れません。しかし、–B dynamic を指定すると、リンカーは、指定されたディレクトリ内で、最初に共有オブジェクトを検索し、次にアーカイブを検索します。
前述の例の詳しい説明として、リンカーはまず libfoo.a を探します。次にリンカーは libbar.so を探し、見つからない場合に libbar.a を探します。
コマンド行上のアーカイブの位置は、作成される出力ファイルに影響を及ぼします。リンカーはアーカイブを検索して、以前に参照したことのある定義されていない仮の外部参照だけを解決します。この検索が完了し、必要な再配置可能オブジェクトが抽出された後で、リンカーはコマンド行上の次の入力ファイルに移動します。
このためデフォルトでは、コマンド行上で先行するアーカイブを、後続の入力ファイルからの新しい参照の解決に使用することはありません。たとえば、次のコマンドでは、file1.c で得たシンボル参照を解決するためだけに、libfoo.a を検索するように、リンカーに指示しています。libfoo.a アーカイブは、file2.c または file3.c のシンボル参照を解決するためには使用できません。
$ cc -o prog file1.c -Bstatic -lfoo file2.c file3.c -Bdynamic
あるアーカイブからのメンバーの抽出をほかのアーカイブからのメンバーの抽出で解決しなければならないというように、アーカイブ間に相互依存関係が存在する場合があります。依存関係が循環している場合は、前方の参照を解決するために、コマンド行上でアーカイブを繰り返し指定する必要があります。
$ cc -o prog .... -lA -lB -lC -lA -lB -lC -lA
アーカイブの指定を繰り返し決定したり維持したりすることは、面倒な作業です。–z rescan-now オプションを指定すると、この処理は簡単になります。–z rescan-now オプションは、コマンド行でこのオプションが検出されると、すぐにリンカーで処理されます。このオプションより前にコマンド行で処理されたすべてのアーカイブは、すぐに再処理されます。この処理は、シンボル参照を解決する追加のアーカイブメンバーの位置を特定しようとします。アーカイブ全体を走査しても新しい再配置可能オブジェクトが抽出されないと、アーカイブの再走査は終了します。前述の例は、次のように単純化できます。
$ cc -o prog .... -lA -lB -lC -z rescan-now
また、–z rescan-start および –z rescan-end のオプションを使用すると、相互に依存するアーカイブを 1 つのアーカイブグループにまとめることができます。結びの区切り文字がコマンド行に書かれていると、これらのグループはリンカーですぐに再処理されます。グループ内で見つかったアーカイブは再処理され、シンボル参照を解決する追加アーカイブメンバーを検出しようとします。このアーカイブ再走査は、渡されたアーカイブグループに新しいメンバーが検出されなくなるまで続けられます。アーカイブグループを使用すると、前の例は次のように書くことができます。
$ cc -o prog .... -z rescan-start -lA -lB -lC -z rescan-end
これまでの例はすべて、コマンド行に指定されたライブラリの検索場所をリンカーが認識していることを前提にしています。デフォルトでは、32 ビットオブジェクトをリンクする場合、リンカーがライブラリを検索するディレクトリとして認識しているのは、2 つの標準的なディレクトリ /lib とそのあとの /usr/lib だけです。64 ビットオブジェクトをリンクする場合は、2 つの標準的なディレクトリ /lib/64 と /usr/lib/64 だけを使用します。これ以外のディレクトリを検索させたい場合には、リンカーの検索パスに明示的に付加する必要があります。
リンカー検索パスを変更するには、コマンド行オプションを使用する方法と、環境変数を使用する方法があります。
–L オプションを使用すると、ライブラリ検索パスに新しいパス名を追加できます。このオプションは、コマンド行上で遭遇したその地点で、検索パスを変更します。たとえば、次のコマンドは、path1、/lib、/usr/lib の順に libfoo を検索します。このコマンドは、path1、path2、/lib、/usr/lib の順に libbar を検索します。
$ cc -o prog main.o -Lpath1 file1.c -lfoo file2.c -Lpath2 -lbar
–L オプションを使用して定義されたパス名は、リンカー専用です。これらのパス名は、作成される出力ファイルイメージには記録されません。したがって、実行時リンカーはこれらのパス名を使用できません。
–Y オプションを使用すると、リンカーが検索するデフォルトのディレクトリを変更できます。このオプションに指定する引数は、ディレクトリのリストをコロンで区切った書式で示します。たとえば、次のコマンドは、ディレクトリ /opt/COMPILER/lib と /home/me/lib 内だけを調べて libfoo を検索します。
$ cc -o prog main.c -YP,/opt/COMPILER/lib:/home/me/lib -lfoo
–Y オプションを使用して指定したディレクトリは、–L オプションを使用して補足できます。多くの場合、コンパイラドライバには、コンパイラ固有の検索パスを指定するための –Y オプションがあります。
環境変数 LD_LIBRARY_PATH を使用しても、リンカーのライブラリ検索パスに付加できます。一般に、LD_LIBRARY_PATH には、コロンで区切られたディレクトリリストを取ります。LD_LIBRARY_PATH のもっとも一般的な書式は、セミコロンで区切られた 2 つのディレクトリリストです。これらのリストは、コマンド行で提供される –Y リストの前後に検索されます。
ここでは、LD_LIBRARY_PATH の設定と、いくつかの –L を指定したリンカーの呼び出しを組み合わせています。
$ LD_LIBRARY_PATH=dir1:dir2;dir3 $ export LD_LIBRARY_PATH $ cc -o prog main.c -Lpath1 .... -Lpath2 .... -Lpathn -lfoo
有効な検索パスは、dir1:dir2:path1:path2:....:pathn:dir3:/lib:/usr/lib です。
LD_LIBRARY_PATH 定義の一部にセミコロンが指定されてない場合は、指定されたディレクトリリストは、–L オプションのあとで解釈されます。次の例では、有効な検索パスは path1:path2:....:pathn:dir1:dir2:/lib:/usr/lib です。
$ LD_LIBRARY_PATH=dir1:dir2 $ export LD_LIBRARY_PATH $ cc -o prog main.c -Lpath1 .... -Lpath2 .... -Lpathn -lfoo
実行時リンカーは、デフォルトでは 2 つの場所で依存関係を検索します。32 ビットオブジェクトを処理する場合、デフォルトでは /lib と /usr/lib が検索されます。64 ビットオブジェクトを処理する場合、デフォルトでは /lib/64 と /usr/lib/64 が検索されます。このほかのディレクトリを検索する場合は、実行時リンカーの検索パスに明示的に追加する必要があります。
動的実行可能ファイルまたは共有オブジェクトが別の共有オブジェクトとリンクされるとき、これらの共有オブジェクトは依存関係として記録されます。このような依存関係は、プロセスの実行中に実行時リンカーによって再配置される必要があります。動的なオブジェクトをリンクする場合は、出力ファイルに 1 つ以上の検索パスを記録できます。この検索パスは、「実行パス」と呼ばれます。実行時リンカーは、オブジェクトの実行パスを使用して、オブジェクトの依存関係を特定します。
–z nodefaultlib オプションを使用すると、実行時にデフォルトの場所を検索しない特別なオブジェクトを作成できます。このオプションを使用すると、オブジェクトのすべての依存関係はその「実行パス」を使用して検索されます。このオプションがないと、実行時リンカーの検索パスをどのように拡張しても、最後に使用された検索パスが常にデフォルトの場所になります。
コロンで区切られたディレクトリリストを指定する –R オプションを使用すると、動的実行可能ファイルまたは共有オブジェクト内に実行パスを記録できます。次の例では、動的実行可能ファイル prog 内に実行パス /home/me/lib:/home/you/lib が記録されます。
$ cc -o prog main.c -R/home/me/lib:/home/you/lib -Lpath1 \ -Lpath2 file1.c file2.c -lfoo -lbar
共有オブジェクトの依存関係を取得するとき、実行時リンカーはまず上記パスを検索してから、デフォルトの場所を検索します。この場合、この実行パスは、libfoo.so.1 と libbar.so.1 の検索に使用されます。
リンカーには複数の –R オプションを指定できます。複数指定された場合は、コロンで区切って連結されます。したがって、上記の例は次のように示すこともできます。
$ cc -o prog main.c -R/home/me/lib -Lpath1 -R/home/you/lib \ -Lpath2 file1.c file2.c -lfoo -lbar
さまざまな場所にインストールされる可能性のあるオブジェクトについては、$ORIGIN 動的ストリングトークンを使用すると、柔軟に実行パスを記録できます。関連する依存関係の配置を参照してください。