arc の日記

はてなダイアリーから引っ越してきました。さらに新しい記事は https://junkato.jp/ja/blog/ で書いています。

Qt(キュート) on Cygwin

クロスプラットフォーム

様々なOSで動く同じ機能を持ったプログラムを作るとき、一番問題になるのがGUI─つまり見た目の部分の処理だ。計算などの機械的な処理は今や同じコードを書いてあとはコンパイラに任せれば済むことが多いが、GUIまわりの実装はOSによって全然違うので、そこはOSごとに別々のコードを書かないといけない。確かに、Windows(xpではLuna, VistaではAero)とMacintosh(?でAqua),Linux(GNOMEKDE)…ユーザインターフェースはOSの数以上に様々な種類がある。しかし考えてみると、ボタンやウィンドウなど、各インターフェースには共通項も多い。プログラマにしてみれば負担が増えるのは嫌でも、ユーザから見ればインターフェースの差だけでプログラムの機能が利用できなくなるなんて、ちょっとおかしい。
そこで、プログラマの負担は増やさず、多くのインターフェースに対応するコードを書ける「GUIツールキット」の出番である。このようなツールキットを使ってひとつのコードが複数のプラットフォームで動く状態を、「クロスプラットフォーム」と言う。

GUIツールキット

有名なGUIツールキットにはGtk+2とQtの二種類がある。

ツールキット名 Gtk+2 (GIMP Toolkit +2) Qt
開発言語 C C++
それぞれを利用したLinuxデスクトップ環境 GNOME KDE

GUIツールキットは、基本的に開発言語のライブラリとして提供される。(Gtk+2は、他言語へのバインディングも複数用意されている。)必要なライブラリを#includeなどで読み込んでGUI用の関数を定義し、それらを呼び出して使う。
さて、何かをクロスプラットフォームにする、ということは、基本的には各プラットフォームの共通項、つまり積集合(ベン図で集合の重なった部分)の機能を実現する、ということだ。すると当然、各プラットフォームに依存するネイティブなコードを書いたときより、実現できる機能は制限される。だから、ツールキットは各OSの持つ先進的な機能は利用できないことが多い。
そんなふうにある意味ツールキットを軽視していて、今作ろうとしているゲームに必要となる機能が用意されていることは、はなからあまり期待していなかったのだが、どうもQtはバージョン4.1あたりから不定形ウィンドウがらみのおいしい機能が採用されていて、Win32APIにおけるUpdateLayeredWindowをうまくラップしてるとすれば普通に使いものになりそうなことが判明。もしかするとこれはゲーム作りにも十分使えるかもしれない、と思い、さらにいろいろ調べつつこの記事を書いている。

Qt on MinGW

Qtは、すぐに使えるようバイナリ版が配布されており、Windowsgccの最小セットMinGWで使うことを想定してコンパイルしたものが用意されている。これをダウンロードしてインストールし、MinGWを使うためのシェル、MSYSあるいはMS-DOSプロンプトで実行ファイルの生成を試み、その後、Cygwinで同じことができるようにする。なお、Cygwinから直接、最新のQtが使える環境を整えることは、現時点では無理っぽい。できたら教えてえろい人。

Qt on MSYS or MS-DOS Prompt

まず、コンピュータの管理、環境変数からPATHにQtのバイナリが格納されたディレクトリを追加する。例えばC:\qt\4.3.2\bin;。こうして、MSYSやMS-DOSプロンプトからGNU Make用のMakefileを作成するプログラムqmakeなどが使えるようにする。
examples内に豊富にサンプルが用意されているので、適当なものを選んで、MSYSから、そのディレクトリでqmakeを実行。Makefileが三種類生成される。Makefile.Release, Makefile.Debug, それら二つを包含するMakefileである。これらでmake(mingw32-make)すれば、例えばMakefile.releaseならreleaseフォルダに実行ファイルが生成され、きちんと実行できるようになっている。

Qt on Cygwin

MSYSに使い慣れていない人ならCygwinでQtを使いたいこともあるだろう。そこで、CygwinでQtが使えるようにしてみる。

CygwinMinGWgccを使うように設定する

まず、Cygwinで普通にプログラムをコンパイルしようとするとCygwinに依存する(あるDLLを実行に要する)バイナリを生成してしまう。-mno-cygwinオプションを指定すればMinGWと同等な機能を使えるが、Makefile中でいろいろ面倒が起きるので、Cygwin上でMinGWを使うように設定する。どうすれば Cygwin 環境内で MinGW を使えますか?にあるように、環境変数PATHの先頭に/cygdrive/c/MinGW/binなどを挿入すればいい。具体的には、bashシェルを使っているなら、.bashrcでexport PATH=/cygdrive/c/MinGW/bin:$PATHという行を追加すれば、bash起動時に自動的に環境変数が調整される。
こうして、Cygwin上でgccを呼び出したとき、MinGWgccが呼ばれるようになった。

CygwinからMinGWのqmakeをがんばって使う

そのままの状態でqmakeすると、QMAKESPEC confファイルの「/usr/lib/qt3/mkspecs/cygwin-g++\qmake.conf」が読めないと言われてしまう。qmakeは、オプションを指定しない場合、Qtのインストールディレクトリ内のmkspecsにあり、qmakeを呼び出したプラットフォームに適したconfファイルを自動で読むようになっている。MSYSの場合はwin32-g++\qmake.confが読まれている。Cygwinだとプラットフォーム名がcygwin-g++になるので、自動での読み込みは期待できない。そこで、-specオプションを付けてqmakeすることを考える。これは、confファイルをこちらで指定してやるオプションだ。ただ、ふつうにqmake -spec /cygdrive/c/Qt/4.3.2/mkspecs/win32-g++としてもうまくいかない。「/cygdrive/c/Qt/4.3.2/mkspecs/win32-g++\qmake.conf」が読めないと言われる。MSYS(MinGW)ではディレクトリの区切りが「\」なのに対し、Cygwinは「/」である。Cygwinから指定された/区切りのパスに、MinGW用qmakeがqmake.confを補完し、エラーが起きるのだ。さらに、Cygwinでふつう「/cygdrive/c/」にマウントされるCドライブには、MSYSでは「c:\\」でアクセスする。そこでqmake -spec c:\\Qt\\4.3.2\\mkspecs\\win32-g++というようにMSYS向けのオプションを指定してやると、うまくいく。
まとめると、.bashrcにalias qmake='qmake -spec c:\\Qt\\4.3.2\\mkspecs\\win32-g++'などという行を付与するなどして、qmakeに自動的にこのオプションを指定するようにすればいい。

CygwinからMinGWのmakeをがんばって使う?

ここまでの作業でふつうにMakefileが生成されるが、肝心のmakeで「複数のターゲットパターンです。中止」と言われてしまう。パッと見、Makefileの文法はおかしくはないのだが…
試しにMSYSのmake(例えば/cygdrive/msys/1.0/bin/make)を使うと、ふつうにうまくいく。
まさか…

arc@x32 / $ /cygdrive/c/msys/1.0/bin/make -v
GNU Make version 3.79.1, by Richard Stallman and Roland McGrath.
Built for i686-pc-msys
Copyright (C) 1988, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 2000
Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.

Report bugs to .
arc@x32 / $ make -v
GNU Make 3.81
Copyright (C) 2006 Free Software Foundation, Inc.
これはフリーソフトウェアです. 利用許諾についてはソースを
ご覧ください.
商業性や特定の目的への適合性の如何に関わらず, 無保証です.

This program built for i686-pc-cygwin

というわけで、GNU Makeのバージョンが新しすぎるとうまくいかないらしい。あと、mingw32-make(GNU Make 3.80)でもいけた。仕方ないのでalias omake='/cygdrive/c/msys/1.0/bin/make'を.bashrcに指定し、omakeを使うことにして解決した。おまけ?なんかかわいい。

Qt with Eclipse

ここまで数時間かけてQtをCygwinで使えるようにしたが、ネットはなんとも広大なもので、Eclipseという統合開発環境を使って簡単にQtのプログラムをコンパイルできるやりかたがとある人の日記に書いてあった。話が逸れるが、この、とある人、面白いレンダラを作っている。今、学科の実験でレンダラを実行できるCPUを設計しているので、ちょっと気を惹かれた。
もともと、Qtを使う程度の規模のプログラム開発なら、よほどCygwin環境に慣れている人でなければ統合開発環境を使ったほうが楽なのは自明。ふつうの人にはそちらの方法がお勧め。

Qt with Visual Studio 2005

ついでにVS2005でQtを使うための情報もリンクしておく。英語でOKなら原文がいい。あとは公式のFAQが役立つかも。

Qt without dependencies

MinGWからQtを使って作成したバイナリは、実行にMinGWのランタイムDLLが必要となってしまう。その依存関係を解決する方法を見かけたのでリンクしておく。ここで./configureする際は、-specが使えないのでconfファイルを自動で読めなければならず、けっきょくMSYSが必要になるようだ。Cygwinだとダメだし、MS-DOSプロンプトで試してもうまくいかなかった。

ちなみに、Intel Pentium3 1.8GHz, メモリ1.5GBの環境で、./configure -static, mingw32-make sub-srcにかれこれ2時間近くかかった。ファイルの総量2GB超。何というツールキット…。