第16章 GCC でのライブラリーの使用

この章では、コード内でのライブラリーの使用について説明します。

16.1. ライブラリーの命名規則

特別なファイルの命名規則をライブラリーに使用します。foo として知られるライブラリーは、libfoo.so または libfoo.a ファイルとして存在する必要があります。この規則は、リンクする GCC の入力オプションで、自動的に理解されますが、出力オプションでは理解されません。

  • ライブラリーにリンクする場合には、-lfoo のように、-l オプションと foo の名前でしか、ライブラリーを指定することはできません。

    $ gcc ... -lfoo ...
  • ライブラリーの作成時には、libfoo.so または libfoo.a など、完全なファイル名を指定する必要があります。

その他のリソース

16.2. GCC でのライブラリーの使用

ライブラリーは、プログラムで再利用可能なコードのパッケージです。C または C++ ライブラリーは、以下の 2 つの部分で構成されます。

  • ライブラリーコード
  • ヘッダーファイル

ライブラリーを使用するコードのコンパイル

ヘッダーファイルでは、ライブラリーで提供する関数や変数など、ライブラリーのインターフェースを記述します。コードをコンパイルする場合に、ヘッダーファイルからの情報が必要です。

通常、ライブラリーのヘッダーファイルは、アプリケーションのコードとは別のディレクトリーに配置されます。ヘッダーファイルの場所を GCC に指示するには、-I オプションを使用します。

$ gcc ... -Iinclude_path ...

include_path は、ヘッダーファイルのディレクトリーへの実際のパスに置き換えます。

-I オプションは、複数回使用して、ヘッダーファイルを含むディレクトリーを複数追加することができます。ヘッダーファイルを検索する場合は、-I オプションで表示順に、これらのディレクトリーが検索されます。

ライブラリーを使用するコードのリンク

実行可能なファイルをリンクする場合には、アプリケーションのオブジェクトコードおよび、ライブラリーのバイナリーコードの両方が利用できる状態でなければなりません。静的および動的ライブラリーのコードは、形式が異なります。

  • 静的なライブラリーは、アーカイブファイルとして提供します。静的なライブラリーには、一連のオブジェクトファイルが含まれます。アーカイブファイルのファイル名の拡張子は、.a となっています。
  • 動的なライブラリーは共有オブジェクトとして提供します。動的なライブラリーの形式は実行可能ファイルで、共有オブジェクトのファイル名の拡張子は .so となっています。

アーカイブファイルまたは共有オブジェクトファイルの場所を GCC に渡すには、-L オプションを使用します。

$ gcc ... -Llibrary_path -lfoo ...

library_path はライブラリーのディレクトリーへの実際のパスに置き換えます。

-I オプションは、複数回使用して、ディレクトリーを複数追加することができます。ライブラリーを検索する場合は、-L オプションで表示順に、これらのディレクトリーが検索されます。

オプションの指定順は重要です。対象のライブラリーがディレクトリーにリンクされていることが分からないと、GCC は、ライブラリー foo をリンクできません。そのため、-L オプションを使用して先にライブラリーディレクトリーを指定してから、-l オプションでライブラリーをリンクするようにしてください。

1 つの手順でライブラリーを使用するコードをコンパイルとリンクする方法

gcc コマンド 1 つでコードをコンパイルリンクできる場合には、上記のオプションを一度に使用します。

その他のリソース

16.3. GCC での静的ライブラリーの使用

静的ライブラリーは、オブジェクトファイルを含むアーカイブファイルとして提供します。リンク後には、作成される実行可能ファイルで必要不可欠な部分になります。

前提条件/事前作業

手順

ソースとオブジェクトファイルからのプログラムをリンクするには、静的にリンクされたライブラリー foo (libfoo.a として検索可能) を追加します。

  1. コードが含まれるディレクトリーに移動します。
  2. foo ライブラリーのヘッダーで、プログラムソースファイルをコンパイルします。

    $ gcc ... -Iheader_path -c ...

    header_path は、foo ライブラリーのヘッダーファイルを含むディレクトリーへのパスに置き換えます。

  3. プログラムを foo ライブラリーとリンクします。

    $ gcc ... -Llibrary_path -lfoo ...

    library_pathlibfoo.a ファイルを含むディレクトリーへのパスに置き換えます。

  4. あとでプログラムを実行するには、以下を実行するだけです。

    $ ./program
注意

静的リンクに関連する -static GCC オプションでは、動的リンクを使用できません。代わりに、-Wl オプションを使用して、リンカーの動作を正確に制御してください。「GCC で静的および動的ライブラリー両方の使用」 を参照してください。

16.4. GCC での動的ライブラリーの使用

動的ライブラリーは、スタンドアロンの実行可能ファイルとして提供します。このファイルは、リンク時、ランタイム時に必要です。これらのファイルは、アプリケーションの実行ファイルからは独立しています。

前提条件/事前作業

プログラムの動的ライブラリーへのリンク

動的ライブラリー foo にプログラムをリンクする手順:

$ gcc ... -Llibrary_path -lfoo ...

プログラムを動的ライブラリーにリンクすると、作成されるプログラムは常にランタイム時にライブラリーを読み込む必要があります。ライブラリーの場所を特定するオプションは 2 つあります。

  • 実行可能ファイルに保存された rpath の値を使用する方法
  • ランタイム時に LD_LIBRARY_PATH 変数を使用する方法

実行可能ファイルに保存された rpath の値を使用する方法

rpath は、リンク時に実行可能ファイルの一部として保存される特別な値です。その後、実行可能ファイルからプログラムを読み込む時に、ランタイムリンカーが rpath の値を使用してライブラリーファイルの場所を特定します。

GCC とリンクし、library_path のパスを rpath として保存します。

$ gcc ... -Llibrary_path -lfoo -Wl,-rpath=library_path ...

library_path のパスは、libfoo.so ファイルを含むディレクトリーを参照する必要があります。

注意

-Wl,-rpath= オプションのコンマの後に、スペースがあるので注意してください。

あとでプログラムを実行するには、以下を実行します。

$ ./program

LD_LIBRARY_PATH 環境変数を使用する方法

プログラムの実行可能ファイルに rpath がない場合は、ランタイムリンカーは LD_LIBRARY_PATH の環境変数を使用します。この変数の値は、共有オブジェクトがあるパスに合わせて、プログラム毎に変更する必要があります。

rpath セットがなく、ライブラリーが library_path パスにある状態で、プログラムを実行します。

$ export LD_LIBRARY_PATH=library_path:$LD_LIBRARY_PATH
$ ./program

rpath の値を空白にすると柔軟性が出てきますが、プログラムを実行するたびに、LD_LIBRARY_PATH の変数を設定する必要があります。

ライブラリーのデフォルトのディレクトリーへの配置

ランタイムのリンカー設定では、複数のディレクトリーを動的ライブラリーファイルのデフォルトの場所として指定します。このデフォルトの動作を使用するには、ライブラリーを適切なディレクトリーにコピーしてください。

動的リンカーの動作に関する全説明は、本書の対象外です。詳しい情報は、以下のリソースを参照してください。

  • 動的リンカーの Linux man ページ:

    $ man ld.so
  • /etc/ld.so.conf 設定ファイルの内容:

    $ cat /etc/ld.so.conf
  • 追加設定なしに動的リンカーにより認識されるライブラリーのレポート (ディレクトリーを含む):

    $ ldconfig -v

16.5. GCC で静的および動的ライブラリー両方の使用

場合によっては、静的ライブラリーと動的ライブラリーの両方をリンクする必要があります。このような場合には、課題が浮上します。

前提条件/事前作業

概要

gcc は、動的、静的ライブラリーの両方を認識します。-lfoo オプションが指定されている場合には、gcc は、動的にリンクされた foo ライブラリーを含む共有オブジェクト (.so ファイル) の場所をまず特定し、静的ライブラリーを含むアーカイブファイル (.a) を検索します。そのため、今回の検索の結果、以下の状態になります。

  • 共有オブジェクトのみが見つかり、gcc がそのオブジェクトに動的にリンクする
  • アーカイブファイルのみが見つかり、gcc がそのファイルに静的にリンクする
  • 共有オブジェクトとアーカイブファイルの両方が見つかり、gcc はデフォルト設定のとおりに共有オブジェクトに動的にリンクする
  • 共有オブジェクトもアーカイブファイルも見つからず、リンクに失敗する

このようなルールがあるので、リンクするために、静的または動的ライブラリーを選択する場合は gcc が検索可能なバージョンのみを指定するようにします。これは、-Lpath オプションで指定する場合に、静的/動的ライブラリーを含むディレクトリーを追加するか、追加しないかである程度制御することができます。

また、動的リンクがデフォルトの設定であるため、明示的にリンクを指定する必要があるのは、静的/動的の両バージョンのライブラリーを静的にリンクする必要がある場合のみです。考えられる方法は以下の 2 つです。

  • -l オプションではなく、ファイルパスで静的ライブラリーを指定する
  • -Wl を使用してリンカーに操作を渡す

ファイルで静的ライブラリーを指定する方法

通常、gcc は、-lfoo オプションを指定して、foo ライブラリーにリンクするように設定しますが、代わりに、ライブラリーを含む libfoo.a への完全パスを指定することも可能です。

$ gcc ... path/to/libfoo.a ...

ファイルの拡張子 .a から、gcc は、このファイルはプログラムとリンクするためのライブラリーであることを理解します。ただし、ライブラリーパスへの完全なパスを指定するのは柔軟な方法ではありません。

-Wl オプションの使用

gcc オプションの -Wl は、基盤のリンカーにオプションを渡すための特別なオプションです。このオプションの構文は、他の gcc オプションとは異なります。このオプションの後に、リンカーのオプションのコンマ区切りのリストを指定して、スペースで区切る gcc オプションと混同されないようにします。

gcc が使用する ld リンカーには、-Bstatic-Bdynamic のオプションがあり、このオプションの後に来るライブラリーが静的、または動的にリンクすべきかどうかを指定します。-Bstatic とライブラリーをリカーに渡した後、以降のライブラリーを -Bdynamic オプションで動的にリンクするには、デフォルトの動的リンクの動きを手動で復元する必要があります。

プログラムをリンクするには、まず 静的に (libfirst.a) ライブラリーをリンクして、ルギに 動的に (libsecond.so) リンクします。

$ gcc ... -Wl,-Bstatic -lfirst -Wl,-Bdynamic -lsecond ...
注記

gcc は、デフォルトの ld 以外のリンカーを使用するように設定できます。-Wl オプションは、gold リンカーにも適用されます。

その他のリソース