Scroll to navigation

LIBTOOL(301) LIBTOOL(301)

名前

libtool - ライブラリのコンパイル・ビルド・ インストール・アンインストールをする

書式

libtool [-n] [--config] [--debug] [--dry-run] [--features] [--finish] [--mode=MODE] [--quiet] [--silent] [MODE-ARGS...]

リンクモード: [-lNAME] [-o OUTPUT-FILE] [-LLIBDIR] [-R LIBDIR] [-all-static] [-avoid-version] [-dlopen FILE] [-dlpreopen FILE] [-export-dynamic] [--export-symbols FILE] [--export-symbols REGEX] [--module] [-no-undefined] [-release RELEASE] [-rpath LIBDIR] [-static] [-version-info CURRENT[:REVISION[:AGE]]

実行モード: [-dlopen FILE]

libtool [--features] [--help] [--version]

説明

libtool は静的ライブラリや共有ライブラリの コンパイル・リンク・インストール・アンインストールの複雑さを簡略化する。 異なるプラットフォームそれぞれで、完全な機能を 統一的なインターフェースを介して使用することができ、 プラットフォーム固有の厄介な癖はプログラマーから隠蔽される。

libtool はコンパイル・実行・リンク・フィニッシュ・インストール・アンインストール という 6 つのモードで動作できる。

コンパイルモード

コンパイルモードの場合、MODE-ARGS は 標準的なオブジェクトファイルを作成するために使われる コンパイラコマンドである。 これらの引き数は C コンパイラの名前で始まり、 オブジェクトファイルのみを作成するよう、 -c コンパイラフラグを含んでいなければならない。

libtool は出力ファイルの名前を決定するとき、 ソースファイル名からディレクトリ構成要素を取り除き、 それから C 言語のソースコードの拡張子 `.c' をライブラリオブジェクトの 拡張子 `.lo' に置き換えるという方法を用いる。

共有ライブラリがビルドされる場合、必要な PIC 作成フラグすべてが コンパイルコマンドに挿入される。 -static オプションを指定すると、たとえ --disable-static が 設定されていたとしても、libtool は `.o' ファイルを作成する。

-o オプションが直接サポートされていないプラットフォーム上では (コンパイラによって作成されたオブジェクトファイルのロックと移動により) エミュレートを行う。 したがって、以下のような通常の構文を使うことができる。

lightside:% libtool cc -c foo/x.c -o foo/x.lo

プラットフォームが -c-o オプションをサポートしていない場合、 古い `foo/x.o' を上書きせずに `foo/x.lo' をビルドすることはできない。 この場合、`foo/x.o' が `foo/x.lo' の後に (再) ビルドされることを 確かめておかなければならない。

リンクモード

リンクモードはライブラリや実行可能プログラムを作成するために、 オブジェクトファイル (ライブラリオブジェクトも含む) をリンクする。

MODE-ARGS は、C コンパイラがオブジェクトファイルから (-o フラグにより) 出力ファイル OUTPUT-FILE を作成する ときに使用するコマンドで構成される。 以下のように、ファイルの形式は OUTPUT-FILE の拡張子に依存する。

.la
libtool ライブラリを作成する。 このライブラリはライブラリオブジェクト (`.lo' ファイル) のみからビルドされなければならない。 -rpath オプションが必要である。 現在の実装では、libtool ライブラリはアンインストールされた他の libtool ライブラリに依存できない。
.a
ar(1) と (あるいは) ranlib(1) を使って 標準ライブラリが作成される。
.o .lo
(一般には `ld -r' を使うことで) 入力ファイルから 再ロード可能なオブジェクトファイルが作成される。 この手法は ``部分リンク'' と呼ばれることが多い。
実行可能なプログラムが作成される。

実行モード

実行モードでは、ライブラリパスの環境変数が自動的にセットされ (そして -dlopen によって修正されて)、プログラムが実行される。

一番目の MODE-ARGS はプログラム名として扱われ、 残りはプログラムの引数として扱われる。

引数の中のどれかが libtool 実行ファイルのラッパーであった場合、 その引数はそれぞれ対応するアンインストール済みバイナリの名前に変換される。 このとき、必要とされるライブラリディレクトリがライブラリパスに加えられる。

インストールモード

インストールモードでは、MODE-ARGScp(1) もしくは BSD-互換の install(1) から始まる インストールコマンドとして解釈する。

残りの MODE-ARGS は、インストールコマンドの 引数として解釈される。

このコマンドは実行され、 インストール後の処理に必要な非特権コマンドもすべて完了する。

フィニッシュモード

フィニッシュモードは、システム管理者の libtool ライブラリ インストール作業を補助し、 libtool ライブラリの探索およびユーザー プログラムへのリンクができるようにする。

MODE-ARG はライブラリディレクトリ名として解釈される。 このコマンドを実行するのにはスーパーユーザー特権が必要なため、 --dry-run オプションを使うと便利だろう。

アンインストールモード

このモードではインストールされたライブラリ (もしくはファイル) を削除する。

一番目の MODE-ARG はファイルを削除するためのプログラム名 (一般には `/bin/rm') である。

残りの MODE-ARGS は削除プログラムの (`-' で始まる) フラグもしくは、 削除するファイルの名前である。

オプション

グローバルオプション

libtool の設定変数を表示して終了する。
シェルスクリプトのトレースモードを有効にして、標準出力に書き出す。
ファイルの作成・修正・削除を行わず、libtool によってどのような コマンドが実行されるかを表示する。
libtool の基本的な特徴を表示する。 また静的ライブラリと共有ライブラリが有効になっているかを表示する。
--mode=finish と同じ。
MODE をオペレーションモードとする。 デフォルトでは、オペレーションモードは MODE-ARGS の内容から推論される。 MODE を指定する場合、次のうちの一つでなければならない。
ソースファイルを libtool オブジェクトにコンパイルする。
他のプログラムがアンインストールされたプログラムやライブラリ (libtool により作成されたもの) を使うことができるように、 ライブラリパスを自動的に設定する。
システムへの libtool ライブラリのインストールを完了する。
ライブラリや実行ファイルをインストールする。
ライブラリや実行ファイルを作成する。
ライブラリや実行ファイルを削除する。
libtool の設定情報を表示して終了する。 このオプションを使うと、パッケージは共有ライブラリと静的ライブラリの どちらを作るか決定できる。
使用法のメッセージを標準出力に表示して、正常終了する。 --mode=MODE が指定されている場合は、 指定されたモードについてのヘルプが表示される。
バージョン情報を標準出力に表示して、正常終了する。

リンクモードオプション

OUTPUT-FILE はインストール済みの ライブラリ libNAME を必要とする。 このオプションは OUTPUT-FILE が実行ファイルでなくても必要とされる。
指定したオブジェクトとライブラリから OUTPUT-FILE を作成する。
必要なインストール済みライブラリを LIBDIR から検索する。
OUTPUT-FILE が実行ファイルの場合は LIBDIR を実行時パスに加える。 OUTPUT-FILE がライブラリの場合は `-RLIBDIR' を DEPENDENCY_LIBS に加える。 これは、そのライブラリが実行ファイルにリンクされるときに必ず LIBDIR を実行ファイルの実行時パスに加えるためである。
OUTPUT-FILE がプログラムの場合は、 そのプログラムをどの共有ライブラリともリンクさせない。 OUTPUT-FILE がライブラリの場合は静的ライブラリを作成するのみである。
どのような種類のバージョニングも行わない (バージョン情報は組み込まれず、シンボリックリンクも作られない)。 このオプションはバージョニングを必要とするプラットホーム上では働かない。
ホストプラットホーム上でネイティブな ダイナミックロードがサポートされていない場合や、 実行ファイルが -static-all-static を 使ってリンクされる場合は、-dlpreopen FILE と同じ。 それ以外の場合は何も影響を及ぼさない。

FILE が `実行ファイル自身' であった場合、 libtool は実行ファイルが -export-dynamic-dlpreopen を使って自らを dlopen(3) できるかを確かめる。

FILE を出力プログラムにリンクし、そのシンボルを LT_PRELOADED_SYMBOLS に加える。

FILE が `出力プログラム自身' であった場合、 出力プログラム自身のシンボルが LT_PRELOADED_SYMBOLS に加えられる。

OUTPUT-FILE のシンボルを dlsym(3) を使って解決できるようにする。
これをサポートしているプラットホーム上では、 リンカは FILE にリストされているシンボルのみをエクスポートする。 FILE の名前は `.sym' で終っていなければならず、 1 行に 1 つのシンボルを含んでいなければならない。 デフォルトではすべてのシンボルがエクスポートされる。
REGEX regex(7) にマッチするシンボルのみがエクスポートされる以外は -export-symbols と同じ。
ダイナミックロードできるライブラリを作成する。 モジュール名は `lib' で始まる必要はないが、 名前の衝突を避けるため `libname' と `name' はパッケージの中で 同時に使用すべきではない。
OUTPUT-FILE が他のライブラリに依存していないことを宣言する。 他のライブラリに依存する共有ライブラリを作れないプラットホームもある。
ライブラリがパッケージのリリース RELEASE で作られたことを指定する。 これによって、ユーザーはどのバージョンが他のものより新しいかを 簡単に判断できる。 このフラグを使うと、パッケージの各リリースのいかなるペアの間にも バイナリ互換はなくなることに注意せよ。 バイナリ互換にしたい場合は、-version-info フラグを使うこと。
OUTPUT-FILE がライブラリの場合、 最終的に LIBDIR にインストールされる。
OUTPUT-FILE がプログラムの場合、 アンインストールされた共有 libtool ライブラリはリンクしない。 OUTPUT-FILE がライブラリの場合、 静的ライブラリを作成するのみである。
-version-info CURRENT[:REVISION[:AGE]]
OUTPUT-FILE が libtool ライブラリであるとき、 ライブラリをビルドするためにインターフェースバージョン情報 CURRENT, REVISION, AGE を使う。 パッケージのリリース情報を指定するために、 このオプションを使ってはいけない。 むしろ -release フラグを参照すべきである。

実行モードオプション

FILE を含んでいるディレクトリをライブラリパスに加える。

バージョニング

libtool は共有ライブラリ用に独自のバージョニングシステムを持っている。 このシステムを使いたい場合は、-version-info オプションを 使わなければならない。 このオプションは CURRENT[:REVISION[:AGE]] という形式の引数を受け付ける。

インターフェースのバージョン。インターフェースとは "外側" の世界に見えるすべてのもので、 変数・関数プロトタイプ・出力形式などである。
CURRENT からの相対値で与える実装のバージョン。
このライブラリが実装している最新のインターフェースと 最古のインターフェースとの違い。 言い替えると、このライブラリは `CURRENT - AGE' から CURRENT までの範囲のすべてのインターフェース番号を実装していて、 このバージョンの範囲にあるライブラリに対して過去にリンクされた すべての実行ファイルは、このライブラリを使うことができる、 ということである。

REVISIONAGE が省略された場合のデフォルトは 0 である。 AGECURRENT インターフェース番号より小さいか 等しくなければならないことにも注意すること。 2 つのライブラリが同一の CURRENT 番号と AGE 番号であるとき、 ダイナミックリンカは大きい REVISION 番号のライブラリを選択する。

バージョニングのガイドライン:

• 1. それぞれの libtool ライブラリについて `0:0:0' というバージョン情報から始めなさい。

• 2. バージョン情報を更新するのは ソフトウェアの公開リリースの直前だけにしなさい。 頻繁な更新は不必要であり、現在のインターフェース番号が大きくなるのを 早くするだけである。

• 3. 前回の更新からライブラリのソースコードが すっかり変更されたなら、REVISION を増加させなさい (C:R:AC:R+1:A になる)。

• 4. 前回の更新からインターフェースが 追加・削除・変更されたなら、CURRENT を増加させ、REVISION を 0 にしなさい。

• 5. 前回の公開リリースからインターフェースが 追加されたなら、AGE を増加させなさい。

• 6. 前回の公開リリースからインターフェースが 削除されたなら、AGE を 0 にしなさい。

パッケージバージョンをライブラリ名にエンコードしたい場合や、 libtool のバージョニングと衝突せずに 他のバージョニングシステムを使いたい場合は、-release を使うこと。 たとえば binutils-2.7.0.2 に付属する `libbfd.so.2.7.0.2' は libtool のバージョニングと明らかに衝突する。 `-release 2.7.0' を使えば `libbfd-2.7.0.so.0.0.0' で終ることができる。

異なる CURRENT バージョンのライブラリや 異なる -release のライブラリはバイナリ非互換であろう。

インターフェースの設計

良いライブラリインターフェースを書くには、 練習とライブラリが解決しようとしている問題に対する徹底的な理解が必要である。 良いインターフェースを設計すれば、 頻繁に変更する必要はなく、ドキュメントを更新し続ける必要もなく、 クライアントがライブラリの使い方を再び勉強し続ける必要もないだろう。

設計に対するガイドラインをいくつか示す:

前もって計画を立てる
エントリーポイントを頻繁に削除する必要がないように、 それぞれのインターフェースを最小にするようにしなさい。

インターフェースの変更を避ける
もしインターフェースを再設計する必要があるならば、 クライアントが既に存在するコードを書き直す必要がないように、 互換性のある関数も残しておくようにしなさい。

見えないデータタイプを使う
クライアントがアクセスする必要のあるデータタイプの定義は少ない程良い。 可能ならば、関数がジェネリックポインタ (内部データタイプにキャストすることが可能) を 受け付けるように設計しなさい。 クライアントに直接データを操作させるよりは、 アクセス関数を提供しなさい。 このようするとインターフェースを変更することなく データ構造を自由に変更できる。

ヘッダファイルを使う
それぞれのライブラリについて大域関数・大域変数をヘッダファイルに書いて ライブラリのソースファイルにインクルードしておけば、 気づかずにインターフェースの変更をしてしまっても コンパイラが知らせてくれるだろう。

可能なときはいつでも静的 (もしくは等価なもの) を使う
ライブラリに大域関数が少ないほど、ライブラリは柔軟に変更できる。 静的な関数・変数は、クライアントがアクセスできないから インターフェースの変更とはならないので、好きなだけ変更することができる。

AUTOMAKE ルールの書き方

libtool ライブラリのサポートは、 LTLIBRARIES プライマリのもとに実装されている。

プログラムを libtool ライブラリにリンクするためには、 ライブラリ名を指定する program_LDADD 変数を使うこと。 libtool に -static といったオプションを渡すためには program_LDFLAGS を使うと良い。

libtool ライブラリをビルドするには、 ライブラリ名を指定する lib_LTLIBRARIES を使うこと。 そして、たとえば、libtool-version-info オプションを 渡すには lib_LDFLAGS を使うこと。 次のセクションに例がある。

作業をするためには、パッケージにいくつかの基本的なファイルを入れたり、 libtoolize を使う必要があるだろう。 libtool スクリプトを直接インクルードしてはならない。

標準システム名を推測しようとする。
標準システム名を確認するサブルーチンスクリプト。
指示されたシステムについて libtool スクリプトを作成する。
基本的な libtool の機能を実装した一般的なスクリプト。

モジュールのダイナミックロード

libtool のダイナミックロード機能を使うためには、 configure.in のなかで AM_PROG_LIBTOOL より前に マクロ AC_LIBTOOL_DLOPEN を使わなければならない。 さもなければ、libtool はそのプラットホームには ダイナミックロードのメカニズムがないと仮定して、 これをシミュレートしようとする。 このシミュレーション機能を使うためには、 実行ファイルをリンクするときに -dlopen-dlreopen フラグを使い、 ダイナミックロードするオブジェクトを宣言しなければならない。 libtool はオブジェクトファイルをリンクし、 以下のような実行ファイルのシンボルテーブルを保持した データ構造を作成する。

struct lt_dlsymlist { const char *NAME; lt_ptr_t ADDRESS; }

NAME には、"fprintf" のような、シンボル名のアスキー文字列が保持される。 ADDRESS は、&fprintf のような、 適切なオブジェクトへのジェネリックポインタである。

const lt_dlsymlist * lt_preloaded_symbols;

この配列は実行ファイルにリンクされている プリロードされたシンボルを表す。 -dlpreloaded されたファイルのそれぞれについて要素が存在し、 ファイル名 NAME と `0' というアドレス ADDRESS、 およびこのファイルからエクスポートされたすべてのシンボルを保持する。 実行ファイル自身については、特別な名前 @PROGRAM@ が使われる。 最後のエレメントは NAME と `0' という ADDRESS を持つ。

ダイナミックロードされるライブラリもしくは、 モジュールをダイナミックロードしようとする実行ファイルをリンクするときは、 -module フラグを指定するのを忘れないこと。

ダイナミックロードしようとしているライブラリの外部シンボルを、 実行ファイルが参照する必要がある場合は、実行ファイルをリンクするときに -export-dynamic を使用すること。

ライブラリ名にバリエーションがあるので、 プログラムはどれがダイナミックロードするための 正しいファイルであるのかを決定する必要がある。 直接的な方法は `.la' ファイルを調べて、
dlname='DLNAME' という行を探すことである。 この行はライブラリをダイナミックロードできない場合は空で、 そうでない場合はライブラリの名前が入っている。

ソースファイル `foo.c', `bar.c' から `libbaz' とよばれるライブラリを作成し、 次に `a' という名前の実行ファイルを作成するために `a.c' を `libbaz' と リンクしようといる。

ライブラリの作成

コンパイルモード:Linux は共有ライブラリをサポートしているので、 libtool は 2 つのオブジェクトファイル、 一つは静的ライブラリ (`foo.lo')、 もう一つは共有ライブラリ (`foo.o') を作成する。 ソースファイル自身へのリンクをコンパイラにやらせたくないので、 -c オプションは必須である。

lightside:~% libtool cc -c foo.c
cc -c -fPIC -DPIC foo.c -o .libs/foo.lo
cc -c foo.c >/dev/null 2>&1
lightside:~% libtool cc -c bar.c
cc -c -fPIC -DPIC bar.c -o .libs/bar.lo
cc -c bar.c >/dev/null 2>&1

リンクモード、静的ライブラリのみをビルドする: 以前に作成された `.o' というオブジェクトファイルを指定している。 -o オプションは必須である。

lightside:~% libtool cc -o libbaz.a foo.o bar.o
ar cru libbaz.a foo.o bar.o
ranlib libbaz.a

リンクモード、静的ライブラリと共有ライブラリをビルドする: `.lo' というオブジェクトファイルを指定する。 必須オプションは、前と同じ -o と ライブラリのインストールされるディレクトリを指示する -rpath である。 ライブラリは `.libs' ディレクトリに作成される。

lightside:~% libtool cc -o libbaz.la foo.lo bar.lo \

-rpath /usr/local/lib cc -shared -Wl,-soname -Wl,libbaz.so.0 \
-o .libs/libbaz.so.0.0.0 foo.lo bar.lo (cd .libs && ln -s libbaz.so.0.0.0 libbaz.so.0) (cd .libs && ln -s libbaz.so.0.0.0 libbaz.so) ar cru .libs/libbaz.a foo.o bar.o ranlib .libs/libbaz.a creating libbaz.la (cd .libs && ln -s ../libbaz.la libbaz.la)

インストールモード:ライブラリを指定したパス (この場合は `/usr/local/lib') にインストールするために 必要なコマンドを実行する。 このモードでは共有ライブラリ (`.so') と静的ライブラリ (`.a') を インストールするとともに、アンインストールと情報提供の目的で libtool ファイル (`.la') がインストールされる。

このモードはふつう特権ユーザーとして実行されるので、 -n または --dry-run オプションを 指定して結果をチェックしておくとよい。

lightside:/tmp% libtool -n install libbaz.la /usr/local/lib
install .libs/libbaz.so.0.0.0 /usr/local/lib/libbaz.so.0.0.0
(cd /usr/local/lib && ln -s libbaz.so.0.0.0 libbaz.so.0)
(cd /usr/local/lib && ln -s libbaz.so.0.0.0 libbaz.so)
install libbaz.la /usr/local/lib/libbaz.la
install .libs/libbaz.a /usr/local/lib/libbaz.a
ranlib /usr/local/lib/libbaz.a
chmod 644 /usr/local/lib/libbaz.a

実行ファイルの作成

最初に `a.c' をコンパイルする

cc -c a.c

ライブラリが既にインストールされている場合には、 普段のように続行することができる

cc a.c -lbaz -L/usr/local/lib

ライブラリがまだインストールされていない場合は、 実行ファイルのリンク・デバッグ・インストールに libtool を使用しなければならない (一度ライブラリがインストールされるまで、これはつづく)。 実際の実行ファイルはインストールされるまで `.libs' 内にあり、 作業ディレクトリにある実行ファイルは単なるラッパーであることに注意すること。

曖昧さを避けるため、絶対に -l-L を使ってアンインストールされた 共有ライブラリにリンクしてはならない。 `.la' ファイルへのパスだけを指定すること。 以下の (`-lm') でわかるように、インストール済みのライブラリは問題ではない。

lightside:~% libtool cc a.o libbaz.la -o a -lm
cc a.o -Wl,--rpath -Wl,/usr/local/lib \

.libs/libbaz.so -o .libs/a -lm lightside:~% libtool gdb a [複雑なデバッグのセッションは省略] lightside:~% libtool install -c a /usr/local/bin/a install -c .libs/a /usr/local/bin/a

Makefile.am の作成

 最初に簡単な configure.in を作成し、 automakelibtool のためのマクロを忘れずに追加する。

AC_DEFUN(AM_INIT_AUTOMAKE)
AC_INIT(a.c)
AM_INIT_AUTOMAKE(a, 1.0)
AC_PROG_CC
AM_PROG_LIBTOOL
AC_OUTPUT(Makefile)

 対応する Makefile.am

# ライブラリのビルド
lib_LTLIBRARIES=libbaz.la
libbaz_la_SOURCES = foo.c bar.c
libbaz_la_LDFLAGS = -version-info 0:0:0
bin_PROGRAMS = a a.debug
# a.c と libbaz.la から a をビルド
a_SOURCES = a.c
a_LDADD = libbaz.la
# 静的デバッグバージョンを作成
a_debug_SOURCES = a.c
a_debug_LDADD = libbaz.la
a_debug_LDFLAGS = -static

 そして最後に実行する

lightside:~% aclocal; libtoolize; automake --add-missing; autoconf
lightside:~% ./configure; make

関連項目


libtoolize(1), libltdl(3)

注意

プログラムのバグについては <bug-libtool@gnu.org> へ報告してください。
この man ページは Ragnar Hojland Espinosa <ragnar@ragnar-hojland.com> が作成しました。

June 2002 libtool 1.4.2