2001/05/09    ROOT-3.01.00-CVS010508 and Problem with flush on MacOS X Release

ROOT 開発元の Fons Rademakers 氏に送ったパッチが CVS に取り込まれたので、再びテストの依頼が来た。今回のものはちゃんとした共有ライブラリーを作ってくれた。ただし、test/{vvector,vmatrix} は TApplication を作るのでなく、gInterpreter->InitializeDictionaries() を呼ぶように修正されていたが、これだとやはり、うまく動かなかったので、これについては報告しておいた。とりあえず CVS 版は使えると言うことで、上記の問題を除き特別なパッチは不要となった。2001/05/08 版の CVS のビルドは root_v3.01.00-cvs010508-macosx.tar.gz

それと、これは http://www.darwinfo.com のメーリングリストアーカイブでも議論されていたが、MacOS X の iostream には flush が効かないという問題がある。次の例で再現できる。

$ cat test.cxx
#include <iostream.h>
int main() {
        double x;
        cout << "Parameter ? " << flush;    // this does not work
        // cout.flush();                    // this does not work either
        // fflush(stdout);                  // though this works OK
        cin  >> x;
        return 0;
}
$ c++ test.cxx -o test
$ ./test
ここで "Parameter ?" と言って欲しいのだが、何も言わない。何か入力するとその時点で出力される。これでは使いものにならない。

問題の flush を含む iostream.o は libstdc++.a に含まれ、そのソースは gcc-3/libio/iostream.{h,cc} であるが、flush の実体をたどっていくと gcc-3/libio/streambuf.cc の中に定義されている streambuf::sync() に行くつく。ところが、この streambuf::sync() は retrun 0 しているだけなのである。どうするのが正しいか不明だが(意図的にこうしてある可能性もある)、とりあえず副作用を最小限にすると言う意味で、streambuf::sync() を変更するのでなく、iostream::flush() に次のような変更を加えた。

--- gcc-3/libio/iostream.cc.ORIG        Wed Aug  9 09:30:13 2000
+++ gcc-3/libio/iostream.cc     Wed May  9 04:39:58 2001
@@ -940,11 +940,16 @@

 ostream& ostream::flush()
 {
- #ifdef MACOSX
+#ifdef MACOSX
        _IO_init_global_stdio ();
 #endif
+#ifndef MACOSX
     if (_strbuf->sync())
        set(ios::badbit);
+#else
+    if (fflush((FILE *)_strbuf))
+       set(ios::badbit);
+#endif
     return *this;
 }

つまり、普通の C の fflush を使うのである。こうすることで一応上の問題は解決した。ただし、これには副作用がある可能性もあるのであくまで実験版と言うことで、libstdc++.a.exp.tar.gz として置いておく。これをトップディレクトリーで展開すると
/usr/lib/gcc/darwin/2.95.2/libstdc++.a.exp
ができるので、同じディレクトリーにある libstdc++.a と置き換えて使う。オリジナルはバックアップしておくのが無難。それとあくまで実験版であるのでいつものように使う場合には自己責任で(2001/05/10 追記:これですが不具合を生ずる場合があることが判明しましたので封印します。当面アプリケーション側で fflush(stdout) として逃げる。いずれにせよ、iostream.o はいろいろなところに既に静的にリンクされているに違いないので不整合を起こす可能性は高い)。

それと、この実験版 libstdc++.a を作っていて気づいたのだが、MacOS X を 10.0.02 にアップデートしてから libtool の挙動がおかしい。これはわたしのところだけの問題だろうか?例えば、ranlib libstdc++.a とかすると、一部の c++ のアプリケーションのリンクで undefined symbols が出るようになってしまう(注意:ranlib は libtool にシンボリックリンクされている)。むやみに libtool を使うと危険。libstdc++.a.exp をわざわざ tarball にしたのはそのため。コピーするなら cp -p を使う事。同じ注意はオリジナルの libstdc++.a をバックアップする場合にも必要。

今までにコンパイルしたMacOS X Release 用の rpm については、 spec ファイル、パッチ、ソース RPM、バイナリー RPM それぞれについて SPECSSOURCESSRPMSRPMS に対応するものが置いてある。RPMS 以下の ppc はマシン依存な RPM 、noarch はマシン非依存な RPM の置き場所である。バイナリーのみの RPM および Tar Ball のみのパッケージの場合には、ソースおよびパッチは src に、また、Tar Ball は tgz にそれぞれ置いてある。新しいものは ~fujiik/macosx/10.0.X/ 以下にある点に注意(~fujiik/macosx 直下のものは Public Beta 用の古いもの)。  いつものように使う場合は自己責任で。


Back to Keisuke Fujii's MkLinux/LinuxPPC Life