Cocoa 使いが wxWidgets を使ってみる (3)

− VMWare + Windows + MinGW で wxMSW を使う −

(2008/11/09 記, 2008/12/08 追記)

 話の途中だが、最終的な目標は Windows(と、できれば Linux)とのクロスプラットフォームアプリの開発である。うちにもめでたく Intel Mac がやってきて、ついでにパッケージ版の Windows XP と VMWare Fusion 2.0 もやってきたので、wxMSW(Windows 版の wxWidgets)でアプリケーションをビルドできるところまでは進めておくことにした。

1. VMWare Fusion 2.0 と Windows XP (Home Edition) のインストール

 これはマニュアル通りに進めるだけ。ただ1点、キーボード配列が JIS と認識されてしまったので、「VMWare Fusion で USキーボード」 という記事を参考に US 配列に直した。一言で言うと、「コントロールパネル」→「システム」→「デバイスマネージャ」→「キーボード」で、ドライバを「PC/AT エンハンス PS/2 キーボード(101/102 キー)」に入れ替える、という方法。Windows については当方ほとんど知識がないので、こういう基本的なところから覚えていかねばならない。

 いやあ、VMWare Fusion いいですねぇ。Mac のデスクトップを背景に Windows が走り出すと、何かとんでもないことが起きている気がして、とてもワクワクしてしまう。PowerPC Mac で最初に Virtual PC を走らせたときも、このワクワク感があったなあ。発売されてすぐ手に入れて、高速とは言えない PowerMac 6300(だったかな?)にインストールして、Windows 使いの後輩(彼とはよく Mac vs Windows のプチ論争をやったが)と2人で Mac の画面を覗き込んで、Windows が立ち上がったら「うわあホントに Windows 走ってるよ!」と大騒ぎしたものだった。BIOS Setup の画面を出して「手が込んでるなあ」と感心したりして。いや話がそれちゃった。

 VMWare Fusion の設定はほとんどデフォルトのままでよいのだが、一点だけ、「共有フォルダ」の設定に手を入れておく。「仮想マシン」→「共有フォルダ」→「共有フォルダの設定を開く...」で設定ダイアログを開き、Mac 上のホームフォルダが共有設定になっていればそれをオフにして、wxWidgets のアプリケーションを作成する作業フォルダ(Xcode のプロジェクトフォルダの置き場所。仮に wxMyProjects とする)を新たに共有するよう設定しておく。こうすると、共有フォルダが z:\wxMyProjects として Windows から見えるようになる。もちろん、ホームフォルダを丸ごと共有してもよいのだが、どうしてもパスが長くなるし、それに Windows 側では慣れない操作で間違ってファイルを消したりする事故が起きやすいので、なるべく共有するのは必要なフォルダに限定した方が安全だと思う。

2. MinGW のインストール

 Windows でプログラム開発するには何を使えばいいんだろう。Microsoft Visual C++Cygwin があるのは以前から知っていた。でも、Visual C++ はお金がかかるし、Cygwin で作ったプログラムは Cygwin をインストールしているマシンでないと走らないみたいだし、どっちもどっちだなあ、と思っていた。最近は無償の Visual C++ Express というのもあるみたいだけど、たぶんこれは使っていると有償版にアップグレードしたくなるように作ってあるんだろうなあ、と思うと、今ひとつ食指が伸びない。パッケージ版の Windows XP 高かったんだぞ、これ以上金を絞り取られてたまるか、と変に身構えてしまう。

 …などと不毛な気合いをみなぎらせつついろいろ調査しているうち、MinGW を見つけた。GCC と最低限のユーティリティで、ランタイムの DLL なしにネイティブの Windows アプリケーションが作れる。MSYS と組み合わせれば、「configure/make」タイプの UNIX アプリのビルドもできる。これだこれだ、こういうのを探してたんだよ。

 さっそくインストールを試みてみたが、どうもうまくいかない。MinGW の標準インストーラは、必要なパッケージをダウンロードするようになっているのだが、ダウンロードが始まって間もなく "Your connection appears to have dropped out. Reconnect dial up or check your IE proxy settings. [再試行][キャンセル]" というダイアログが出て止まってしまう。何度再試行をしてもだめ。IE でネットに直接アクセスすることはできているのだが、VMWare を経由しての接続がダウンローダと相性が悪いのかもしれない。個別のパッケージをダウンロードすることもできる(SourceForge のダウンロードページ)が、そこからのインストールがちょっとややこしい。こんな入口でつまづいてちゃしょうがないな、と思ったので、「MinGW猫科研究所パック」を使わせていただくことにした。これは MinGW + MSYS + msysDTK をパッケージ化したもので、gcc と関連ツール、bash をはじめよく使うコマンド類、autotools などがインストールされる。すべてのファイルは c:\msys 以下に置かれており、ここに c:\msys\1.0\msys.bat へのショートカットが置かれている。このショートカットをダブルクリックすると、コマンドプロンプトで bash が走り始める。c:\msys\1.0 というディレクトリが "/" としてマウントされているようだ。

WinXP command prompt running bash

 Windows でコマンドプロンプトで作業していると、ついうっかり "ls" と打ったりパス区切りをスラッシュにしてしまってずっこけることが多いのだが、これは bash なので安心(?)。ちなみに、"ls /" では見えないが、Windows の c: ドライブの中身は /c/ にマウントされている。従って、例えば「マイドキュメント」は /c/Documents and Settings/Owner/My Documents でアクセスできる(スペースを含んでいるので、もちろんエスケープか引用符は必要)。また、先ほど VMWare で設定した Mac との共有フォルダは /z/wxMyProjects でアクセスできる。

 MSYS 上での「ホームディレクトリ」は /home/Owner である。これは Windows 上では c:\msys\1.0\home\Owner になる。このフォルダのショートカットを作って Windows のデスクトップに置いておくとよい。Mac からファイルをコピーするには、Windows 上でこのフォルダのウィンドウを開いておいて、Mac の Finder からドラッグ&ドロップすればよい。もちろん、z:\wxMyProjects を経由することもできる。

 「猫科研究所パック」には gdb が含まれていなかったので、これだけは手動でインストールした。上記ダウンロードページから GNU Source-Level Debugger を選び、下の方の "Current Release" のバイナリインストーラ (.exe) をダウンロードする。インストール先を c:\msys\1.0\mingw にする( "\mingw" はインストーラが自動的に付加するので、ダイアログ上では c:\msys\1.0 を選べばよい)。インストール後、MSYS のコマンドプロンプトで which gdb と打って /mingw/bin/gdb と返ってくれば成功。

3. wxMSW のビルド

 wxMSW を MinGW でビルドしてみる。wxWidgets の公式ダウンロードページ から、wxMSW-2.8.9.zip を取ってきて、MSYS のホームディレクトリに展開する(バージョン番号は2008年11月9日現在)。Windows 上での作業はここまでで、これ以降は MSYS 上で作業する。

インストーラを使ってもよいが、まあ zip を展開する方が何をやっているかわかりやすく安心なので。

 MSYS のコマンドプロンプトを開いて、次のように進める。

$ cd ~/wxMSW-2.8.9 $ ../configure --with-msw --with-opengl --disable-shared --with-unicode --with-libjpeg=builtin --with-zlib=builtin --disable-threads $ make

 --disable-threads はちょっと要注意。これを入れておかないと、生成したバイナリが MinGW 独自の DLL に依存してしまう。

 configure, make はかなり時間がかかる。特に、configure が思いのほか遅い。1行ごとに一呼吸待つ感じがする。ディスクアクセスに VMWare を経由しているので、そのへんがオーバーヘッドになっているのかな? make install は必要ない。アプリケーションをビルドするときに、今ビルドしたディレクトリを指定すれば済む。

4. wxMac と wxMSW を共通のソースからビルドする

 共通のソースからビルドする…そんなの当然じゃん、クロスプラットフォームだろ、って? そりゃそうなんですけど、同じディレクトリでやりたいじゃないですか。wxMac で修正したソースを wxMSW でビルドするとき、例えばいちいち Mac 側で cvs commit して Window 側で cvs update するなんてめんどくさいじゃないですか。そのために wxMyProjects ディレクトリを共有設定したんだから。しかも、なるべくプロジェクトのトップレベルディレクトリを散らかさないように運用したい。今のところ、こんな具合にやっている。

5. Ruby, CLAPACK のインストール

 wxMSW と直接は関係ないのだが、今作っているアプリでは Ruby, CLAPACK の組み込みを予定しているので、これらをインストールしておいた。

 Ruby は何も問題はない。One-Click Ruby Installer を使ってインストールする。デフォルトでは c:\Ruby にインストールされる。

 CLAPACK は思いのほか苦戦した。わかってしまえば難しくはなかったのだが、手順は次の通り。

 F2CLIBS/libf2c.a, blasMinGW.a, clapackMinGW.a の3つのライブラリができる。これらをそれぞれ libf2c.a, libblas.a, libclapack.a という名前で /lib/clapack に置く。また、INCLUDE/f2c.h, INCLUDE/blaswrap.h, INCLUDE/clapack.h を同じく /lib/clapack にコピーする(ヘッダファイルを /lib 以下に置くのは筋が悪いとお思いなら他の場所でも可)。

 (2008.12.08 追記) wxMSW とリンクすると、libf2c.a が不具合を起こす。シンボル解決の順序の問題なのか、よくわからないのだが、libf2c.a 中の main() 関数がリンクされてしまい、その結果 _MAIN__ が見つからない、というリンクエラーになる。_MAIN__ は f2c で FORTRAN プログラムを C に変換した時のメインルーチンだが、当然そんなものはあるわけがない。main() がリンクされてしまうことが問題なので、次のようにして libf2c.a から main.o を外した。

$ cp libf2c.a libf2c_nomain.a $ ar d libf2c_nomain.a main.o

 Ruby 組み込み用のためのコンパイラフラグはこんな感じになる。

MAC: RUBY_CFLAGS = -I/usr/lib/ruby/1.8/universal-darwin8.0 \ -I/usr/lib/ruby/1.8/universal-darwin9.0 RUBY_LDFLAGS = -lruby MSW: RUBY_CFLAGS = -I/c/Ruby/lib/ruby/1.8/i386-mswin32 RUBY_LDFLAGS = -L/c/Ruby/lib /c/Ruby/bin/msvcrt-ruby18.dll

 Mac で -I オプションを2つ書いてあるのは、MacOSX10.4u.sdkruby.h が含まれていないため。本当は ...darwin8.0ruby.h が見つからないといけないのだが、見つからないので ...darwin9.0(10.5 組み込み)を併記している。MacOSX10.4u.sdk と 10.5 では Ruby のバージョンが違うのでこれはちょっと危なく、10.4 から ...darwin8.0 のヘッダファイルをコピーしてきて MacOSX10.4u.sdk に入れておいた方がいい。まあ、このままでもとりあえずは動いてはいるようだが。

 MSW の方は、上で見て明らかな通り msvcrt-ruby18.dll にバイナリが依存するようになる。これはやむを得ない。スタティックリンクする手もあるのだが、require で「標準添付ライブラリ」を読み込もうとしたとき困ってしまう。スタティックリンクして、「Ruby の別途インストールは不要です、ただし組み込み以外の添付ライブラリは使えません」というのとどちらが親切か、それは作るアプリケーションの目的次第だろう。

 CLAPACK をリンクするためのフラグはこうなる。

MAC: CLAPACK_CFLAGS = -framework Accelerate MSW: CLAPACK_CFLAGS = -I/lib/clapack CLAPACK_LDFLAGS = -L/lib/clapack -llapack -lblas -lf2c_nomain # -lf2c_nomain は 2008/12/08 追記

 Mac は標準で CLAPACK が入っている。インクルードパスは指定していないが、そのかわり #include <vecLib/clapack.h> と書く必要がある。MSW の方は特に問題はない。

6. 例

 スクリーンショットだけ載せてもしょうがないのだが、まあこんな雰囲気だってことで。

My wx application on Mac My wx application on MSW