(2003.11.30新規作成。)
(2004.11.07 リンク切れを修正。)
(2005.7.10 MinGWを追加。)
libtoolは、共有オブジェクト(shared object; so、あるいは動的リンクライブラリ;DLL)を生成するためのMakefileを、環境に依存せずに書くためのプログラム。
利用者(プログラムの開発者)は、Makefileで、仮想的なファイルをコンパイル、あるいはリンクするように書く。libtoolは、それらのファイルに対する操作を解釈して、実際のファイルに対するコンパイルオプションなどを生成し、実行する。
libtoolは、--modeオプションで実行したい操作を区別する。modeによって、libtoolの動作は、まったく異なる。
--modeの値 | 意味 |
---|---|
compile | コンパイル |
link | リンク |
install | インストール |
uninstall | アンインストール |
clean | クリーンアップ |
execute | ライブラリをインストールせずに、ライブラリを使用するプログラムを実行する。 |
finish | 完了メッセージを表示する。 |
Cygwinでは、configure.(ac|in) ファイルを見て、開発版か安定版のいずれかのlibtoolを起動するようになっている。そのため、configureファイルがない場合は、libtoolは、絶対パスで記述する必要がある。
まずはライブラリにするためのファイルをコンパイルする。ここでのファイル名は実在のものを使う。
$ /usr/autotool/devel/bin/libtool --mode=compile gcc -c mydll.cc mkdir .libs gcc -c mydll.cc -DPIC -o .libs/mydll.o gcc -c mydll.cc -o mydll.o >/dev/null 2>&1
ディレクトリ.libsが生成され、必要であれば、本物の生成物はこのディレクトリに入れられる。libtoolは、自動的に適当なコンパイルオプションを追加し(-DPIC など)、コンパイルする。
カレントディレクトリにmydll.lo、mydll.oの二つのファイルが生成される。位置独立なコードオブジェクトとそうでないオブジェクトが区別される環境では、*.o は位置独立ではない、*.lo は位置独立なファイルとなる。
Cygwinでは、mydll.loは、ただのテキストファイル。MinGWでも、mydll.loは単なるテキストファイル。
ライブラリを生成する場合は、libtool --mode=link とする。リンクする対象(オブジェクトファイル)は、*.oではなく*.lo ファイルを指定する。
gccの -o オプションで出力するライブラリのファイル名を指定する。出力ファイルは lib で始まらなければならず、拡張子は、静的ライブラリであれば.a、動的リンクライブラリであれば.la とする。
動的リンクライブラリを出力するときは、libtoolのオプション -rpathを指定しなければならない。このオプションには、ライブラリの最終的なインストール先を指定する。
$ /usr/autotool/devel/bin/libtool --mode=link gcc mydll.lo -o libmydll.aまたは
$ /usr/autotool/devel/bin/libtool --mode=link gcc mydll.lo -o libmydll.la -rpath /usr/local/lib
これで、libmydll.la が生成される。Cygwin / MinGWでは、これもテキストファイル。
Cygwinでは、libtoolのオプション -no-undefined を付けないとリンク時にエラーが発生する。このオプションは、出力ファイルが他のライブラリに依存していないことを宣言するもの。Linux, MinGWでは、-no-undefinedオプションはなくてもいい(付けても問題ない)。
$ /usr/autotool/devel/bin/libtool --mode=link gcc mydll.lo -o libmydll.la \ -no-undefined -rpath /usr/lib gcc -shared .libs/mydll.o -o .libs/cygmydll-0.dll -Wl,--image-base=0x10000000 -Wl,--out-implib,.libs/libmydll.dll.a Creating library file: .libs/libmydll.dll.a ar cru .libs/libmydll.a mydll.o ranlib .libs/libmydll.a creating libmydll.la (cd .libs && rm -f libmydll.la && ln -s ../libmydll.la libmydll.la)
Cygwinでは、次のように、*.dllファイルが生成される。
$ ls .libs/ cygmydll-0.dll libmydll.a libmydll.dll.a libmydll.la libmydll.lai mydll.o
-export-symbols または -export-symbols-regex オプションでエクスポートするシンボルを指定することもできる。付けなければ、すべてのシンボルがエクスポートされる。
(2005.7.10 この節追加。)
ライブラリをインストールするには、libtool --mode=install を使う。installまたはcpコマンドとそのオプションを続けて書く。コピー元は*.laファイル、コピー先はディレクトリにする。
libtool --mode=install [ install | cp ] ...
Linuxでは、次のようになる。
$ libtool --mode=install cp libmydll.la /home/hori/src/test/share/simple/t cp .libs/libmydll.so.0.0.0 /home/hori/src/test/share/simple/t/libmydll.so.0.0.0 (cd /home/hori/src/test/share/simple/t && rm -f libmydll.so.0 && ln -s libmydll.so.0.0.0 libmydll.so.0) (cd /home/hori/src/test/share/simple/t && rm -f libmydll.so && ln -s libmydll.so.0.0.0 libmydll.so) cp .libs/libmydll.lai /home/hori/src/test/share/simple/t/libmydll.la cp .libs/libmydll.a /home/hori/src/test/share/simple/t/libmydll.a ranlib /home/hori/src/test/share/simple/t/libmydll.a chmod 644 /home/hori/src/test/share/simple/t/libmydll.a
オブジェクトファイルなどを一掃するには、libtool --mode=clean とする。
$ /usr/autotool/devel/bin/libtool --mode=clean rm libmydll.la main.lo \ main.o mydll.lo mydll.o testpg testpg.exe rm libmydll.la .libs/libmydll.dll.a .libs/libmydll.a .libs/libmydll.la .libs/libmydll.lai rm main.lo ./.libs/main.o ./main.o rm main.o rm: cannot remove `main.o': No such file or directory rm mydll.lo ./.libs/mydll.o ./mydll.o rm mydll.o rm: cannot remove `mydll.o': No such file or directory rm testpg .libs/testpg .libs/testpgS.o .libs/lt-testpg rm: cannot unlink `.libs/testpg': No such file or directory rm: cannot remove `.libs/testpgS.o': No such file or directory rm: cannot remove `.libs/lt-testpg': No such file or directory rm testpg.exe testpg rm: cannot remove `testpg': No such file or directory rmdir .libs
む、main.o、mydll.o、testpg は不要だったか。
メインプログラムをコンパイルする。これもlibtool --mode=link を使う。
$ /usr/autotool/devel/bin/libtool --mode=compile gcc -g -c main.cc gcc -g -c main.cc -DPIC -o .libs/main.o gcc -g -c main.cc -o main.o >/dev/null 2>&1 $ /usr/autotool/devel/bin/libtool --mode=link gcc -o testpg main.o libmydll.la gcc -o .libs/testpg main.o ./.libs/libmydll.dll.a creating testpg.exe
これで、仮想的な testpg(シェルスクリプト)、仮想的な testpg.exe(何?)、実体である.libs/testpg.exe が生成される。
これらを踏まえて、Makefileを作成すると、次のようになる。-no-undefined と .exe はCygwin依存。完全に差異を吸収するのはなかなか難しい。このほか、Linuxではリンク時に-lstdc++オプションが必要になる。
# Cygwinでは次のようにする LIBTOOL = /usr/autotool/devel/bin/libtool LDFLAGS = EXEEXT = .exe # Linuxでは次のようにする #LIBTOOL = /usr/bin/libtool #LDFLAGS = -lstdc++ #EXEEXT = .SUFFIXES: .cc .lo .la $(EXEEXT) .cc.lo: $(LIBTOOL) --mode=compile gcc -c $< -o $@ testpg$(EXEEXT): main.lo libmydll.la $(LIBTOOL) --mode=link gcc -o $@ $^ $(LDFLAGS) libmydll.la: mydll.lo $(LIBTOOL) --mode=link gcc -o $@ $^ -no-undefined -rpath /usr/local/lib main.lo: main.cc mydll.lo: mydll.cc clean: $(LIBTOOL) --mode=clean rm -rf libmydll.la main.lo mydll.lo testpg$(EXEEXT)
2003.12.03
上記の例では、すべての関数をエクスポートしていた。特定の関数だけエクスポートする場合は、シンボル一覧ファイルを別に用意する。
次のファイルからライブラリを作り、このうちexp_func()だけエクスポートしてみる。
#include <stdio.h> extern "C" { void exp_func(); void no_exp_func(); } void exp_func() { printf("ok.\n"); } void no_exp_func() { printf("failed.\n"); }
次の内容のシンボルファイル dll2.sym を作る。エクスポートするシンボルを1行1シンボルにて記述する。シンボルの先頭に'_'などを付ける必要はない。このシンボル名は、CygwinでもLinuxでも同じものが使える。
exp_func
Makefileでは、次のように書く。libtool の -export-symbols オプションでこのファイルを指定する。
libdll2.la: dll2.lo $(LIBTOOL) --mode=link gcc -o $@ $^ -no-undefined -rpath /usr/local/lib \ -export-symbols dll2.sym
libtoolは、Cygwinの場合は内部で次のファイルを生成し、これをgccに与えることで特定のシンボルだけエクスポートする。
EXPORTS exp_func