Gauche-0.7からautomake+libtool+libltdl化する予定。 ここは作業メモに使う。
info_TEXINFOSにgauche_refe.texi gauche_refj.texiを入れといても automakeを走らせる時にはそれらのファイルが無いから 文句を言われる。 *.texiが自動生成されるケースってのは対象外なのか?
automakeの生成するMakefile.inには、dependency関係部分で gnu makeに依存した構文が挿入されることがある。automake-1.4-p5だと "-include" というディレクティブが入っていた。
automake標準の方法で "make dist" するとこういう構文は展開されて消えるので、 tarballに入るMakefile.in (から生成されるMakefile)は普通のmakeでも使える ものになる。
だが、"make dist" が使えない場合にこういう設計は問題だ。 dependencyの自動生成が難しい問題は承知しているが、やはり Makefileのイディオムの展開という機能と、 ディストリビューションパッケージの作成という機能は別にして欲しいなあ。
AC_CONFIG_HEADERで指定したヘッダファイルのあるディレクトリが 勝手にインクルードパスに追加される。 #include "config.h" と書きたくないからわざわざサブディレクトリに 置いてるんじゃーそれがわからんのかー。
サブディレクトリsubdirにあるファイルfoo.hを、例えばpkghdrdirに インストールしたいとき。
pkghdr_SCRIPTS = subdir/foo.h
とか書いてもだめ。インストール前に $(pkghdrdir)/subdir を作成してくれない。 pkghdrdirにあらかじめsubdirを含ませておくと、$(pkghdrdir)/subdirを 作った後で $(pkghdrdir)/subdir/subdir/foo.h にインストールしようとするからだめ。
install-data-hook とかは自動生成されるinstallの後に走るから ディレクトリの作成には使えない。
scriptの場合はtransformをかけるという技で何とかなるかもしれんが、 ヘッダファイルは無理。install-data-local使って自分でしこしこやるしか ないのかな。
例えば gc/ 以下は単独パッケージにもなれるようなMakefile.amとconfigure.in を持っているわけだけど、これをGauche本体の一サブディレクトリとして 扱いたいんだがうまくいかない。
ああ、ドキュメントに書いてあった。configure.inがサブディレクトリに ある場合はそれぞれでautomakeを走らせなくちゃならないのか。 でもそしたらmake distとかはどうなるんだ?
どっちを作るか、もしくは両方作るか、というのはconfigure時に決定されて しまう。configure.in内の指定でどちらかを強制的にoffにすることはできるが、 「libgaucheだけstaticで、extensionはsharedで」という指定はできない。
MacOS Xでlibgaucheをshared libにすると動いてくれないので、 以下のいずれにするか迷っている。
まー妥当な判断は3.だろーなー。automakeがconfigure.inを複数持つのを 気に入らないからわざわざ一本化したのに、逆戻りか。
libtool捨て、の方向にもかなり惹かれるんだが、 何らかのラッパースクリプトが必要になるのは確かなんで、 libtoolの再発明にしかならない気がする。 実際、0.6.8まではldwrap.shというアドホックなスクリプトを使ってたわけだし。
結局、次の3つを切替えなければならないということか。
Linux, *BSD他 | MacOS X | Cygwin | |
libgaucheのコンパイル | dynamic/staticともに可 | staticのみ可 | dynamicのみ可(*) |
extensionのコンパイル時にlibgauche.laをリンク | libgaucheがdynamicなら可 | 不可 | 必要 |
(*: libgaucheをstaticで生成すると、extensionがコンパイルできない)
extensionのリンク時に-no-undefinedを指定しないと、libtoolは CygwinでDLLを作ってくれない (シンボルを解決するのに必要な ライブラリを全て与えても、だ)。
一方、MacOS Xではgoshをスタティックリンクする必要上、 -no-undefinedは指定できない。
他のunixではどちらでも良い。
DSOに、別ディレクトリで作成されたアーカイブfoo/foo.la中の オブジェクトファイルを全部含めたい場合、libtoolに渡すオブジェクトに foo/foo.laを書いておけば、自動的に--whole-archiveオプションを くっつけてリンカに渡してくれる。
$(LIBTOOL) --mode=link $(CCLD) $(OBJECTS) foo/foo.la $(LDFLAGS) $(LIBS)
問題は、それをするためにlibtoolが引数を解析する際に、通常の.loファイルと .laファイルで別々にリストを作って処理することだ。そのため、 foo/foo.la中のオブジェクトを a.lo と b.lo の間に配置したい場合、
$(LIBTOOL) --mode=link $(CCLD) a.lo foo/foo.la b.lo $(LDFLAGS) $(LIBS)
と書いておいても、実際にリンカに渡される時には
gcc -o hoge.so a.lo b.lo -Wl,--whole-archive foo/foo.la -Wl,--no-whole-archive ...
という具合に順番が変えられてしまう。 まったくもってお節介だ。
HP-UXでテストしてて気づいたんだが、libfoo.a と libfoo.soの両方がある場合、 libtool --mode=install install -m 444 libfoo.la $(DIR) でインストールすると、 libbfoo.aのインストール後にranlibを走らせようとする。
しかし、インストールしたlibfoo.aはmodeが444にされているので書き込めない。 よってエラーとなり、makeが中断する。まあそりゃそうだわな。 なんでranlibが必要なんだろう? 必要だとしても、libtool内で permission を一時的にwritableにするくらいやってほしい。
automakeではなくlibtoolなんだが、mode=finishの時にデフォルトはこんな メッセージが表示される。
---------------------------------------------------------------------- Libraries have been installed in: /usr/local/lib/gauche If you ever happen to want to link against installed libraries in a given directory, LIBDIR, you must either use libtool, and specify the full pathname of the library, or use the `-LLIBDIR' flag during linking and do at least one of the following: - add LIBDIR to the `LD_LIBRARY_PATH' environment variable during execution - add LIBDIR to the `LD_RUN_PATH' environment variable during linking - use the `-Wl,--rpath -Wl,LIBDIR' linker flag - have your system administrator add LIBDIR to `/etc/ld.so.conf' See any operating system documentation about shared libraries for more information, such as the ld(1) and ld.so(8) manual pages. ----------------------------------------------------------------------
これがうざい。しかも、サブモジュール毎に繰り返し表示されるからさらにうざい。 --quietで消せるんだが、そうするとlibtoolが実行するコマンドラインの エコーも出なくなっちゃうんだよね。
こういうメッセージの情報が必要な人間はmakeの出力なんていちいち見ないし、 逆にmakeの出力を見る人間ならこういう情報は知ってるんだから 実行されてるコマンドラインとかの重要な情報に絞って出して欲しいげな。
DLLでエクスポートされるデータの参照がうまくいかんなあ。
(2003/04/22 12:07:12 PDT): ふーむ。従来のdlltoolを使う方法では、 Scm_HogeClassと_imp__Scm_HogeClassの両方がexport symbolリストに 入っていたのだが、 defの作成をbinutilsにおまかせでやると、ソース中で明示的に _imp__Scm_HogeClassが定義されている場合にScm_HogeClass自身がexport symbolsから 外されてしまうようだ。
dlopen()用に作ったfoo.la内のシンボルを、同じくdlopen()用に作ったbar.laから 参照したい場合、リンク行にそのまま並べておくことができる。 (ただ、「ポータブルではない」というwarningが出る)。
$(LIBTOOL) --mode=link $(CCLD) -o bar.la $(bar_OBJECTS) foo.la
そのままfoo.laの実態(.libs/foo.dll)をリンクすることはできないと思うんだが、 どうやってシンボル解決をやってるのか、要調査。
具体的にはext/mt-randomがext/uvectorに依存してるのね。
(2003/04/11 18:01:20 PDT): たぶん、既存のパッケージをautomake化する場合は、 全部automakeにやらせようとしないほうが良いんだろう。 automakeの方法に合うところだけautomakeにやらせて、 後は従来の方法を使えば良いと割り切ることが肝心のような気がしてきた。 Gaucheの場合、tarballの作成は今まで通りDISTスクリプトでやれば良いわけだ。
(2003/04/12 12:34:49 PDT): 今のところ、自分なりの感想はこんなかんじ。
(2003/04/15 11:53:55 PDT): automakeのソースを読んでみた。結局のところ、 automakeのやることはヒューリスティクスのかたまりなんだが、 そのヒューリスティクスがソースにハードコードされているのが automakeに対して感じる違和感の根本原因であるように思えて来た。
configureのやることもヒューリスティクスのかたまりなんだけど、 autoconfは少なくとも、ヒューリスティクスそのものの記述は 処理系の外に出ている。built-in macroで足りなければ、 自分でmacroを書けて、しかも自分で書いたmacroはbuilt-in macroと対等だ。
一方、automakeでは、自分でprimaryを定義することはできない。 (新しいバージョンにはあるのだろうか? 1.6のドキュメントには 少なくとも見付けられなかったが)。 既に提供されてるprimaryの動作をちょっとラップした新しいprimaryを 作ることもできない。提供されているprimaryの動作が気に入らなければ、 自分でmake ruleを書くしかない。
(2003/04/21 23:38:02 PDT): automakeは外した。 考えてみたら、automakeで楽ができるのは基本的に「最初にMakefileを書く人間」と 「パッケージングを行うスタッフ(make distを使う場合)」であって、 他の大部分の、CVSソースをハックする人間にはほとんどメリットが無い。 それなのにCVSソースハッカー全員にautomake, autoconf, libtoolのバージョンを 揃えることを要求するなど、ばかげている。
ついで、libltdlも外す。libltdlの機能はとても欲しいのだけれど、 gaucheをライブラリとして使う場合、他にlibltdlを使っているライブラリが あると衝突してしまう。システムのlibltdlを使うようにすれば衝突は 避けられるが、基本部分に非標準の外部ライブラリへの依存を入れたくはない。
さて、残るはlibtoolなんだが… 現在cygwin上でDLL生成を試みているんだが、 これも道が遠そうだ。libtoolが実行するコマンドを選択する基準が ドキュメントされてないから、結局あのシェルスクリプトを読むはめになる。
(2003/05/18 01:09:37 PDT): ようやく、各プラットフォームでビルドが通りそうな出口が見えてきた。 しかし、configureでプラットフォームを見てコンパイルフラグや リンクフラグをごにょごにょする、という部分を無くしたいから libtoolに期待したのだけれど、結局、まともにビルドするためには、 configureでlibtool自身に与えるフラグを調整する必要があった。
ここまでしてなおlibtoolを使うメリットってなんじゃろか。 まあ、オブジェクトファイルや共有ライブラリのエクステンションの 処理はlibtool内に隠されるので、Makefileを書くときに 一様に *.lo と *.la で書けるというのはメリットだな。
しかし、本来の目的であるconfigure.in内でのプラットフォーム毎の フラグの切替えの除去というのができていない以上、 あの巨大なシェルスクリプトを持ち歩く意味はあんまり無いように 思える。
libtoolが巨大化している理由のひとつは、あらゆる可能性に 対応しようとしているからだと思う。でも、今回のような イレギュラーなケースにまで対応させようとすると、 どんどんスクリプトがふくらんで、メンテ不可能になるんじゃないか。 それなら、ケースバイケースで専用スクリプトを書いた方が よほどすっきりするだろう。
さんざ苦労したので0.7はlibtoolで行くつもりだが、 その後は独自リンクスクリプトに移行するかもしれない。