今更MinGW 2009.06(3) MinGW
MinGWは、C言語の初心者が作成するような単純なmakeレベルの環境は、MSYSとは独立に動作することができる。その構築方法と注意点をここで述べる。
ベース環境(binutils, mingwrt, w32api, mingw-utils, gdb, mingw32-make)
コンパイラ本体であるgccの前に、ベースとなる環境を作成する。コンパイラ本体を同時に入れてしまっても良いのだが、猫科研究所ではgcc3とgcc4を切り替えられるようにすることも命題の1つであるので、ここでは共通であるベース環境を先に準備する。
MinGWのダウンロードページで、以下のファイルを取得してこよう。
- GNU Binutils / Current Release: GNU binutils-2.19.1
- GNU Make / Current Release: mingw32-make-3.81-20080326
- MinGW API for MS-Windows / Current Release: w32api-3.13
- MinGW Runtime / Current Release: mingwrt-3.15.2
- MinGW Utilities / Current Release: mingw-utils-0.3
- GNU Source-Level Debugger / Release Candidate: GDB 6.8-3
これらのファイルは全て/mingw以下(C:\msys\mingw以下)に展開する。
各パッケージの説明
簡単に説明する。
- binutils
- ldやstripなどのリンカやバイナリを操作するツール群
- mingw32-make
- Makefileに従いビルドをある程度自動化するツール
- w32api
- Win32APIをMinGWから使用可能にするファイル群
- mingwrt
- ランタイムライブラリにglibcではなくmsvcrtを使用可能にするファイル群
- mingw-utils
- reimpやa2dll等の主にbinutilsを補佐するツール群
- gdb
- 主にGCC向けのコマンドラインデバッガ
binutilsが無ければリンカがないので.exeや.dllが作成できず、w32apiが無ければWindows固有のプログラミングができない。そしてmingwrtが無ければランタイムがない状態となるのでprintfさえ使用できない。よって、この3つは特に重要だ。
makeに関する注意
makeは、MSYS側でも導入するため重複することになる。ただし、mingw32-makeは名前の通り"mingw32-"というプレフィックスが付くために、使い分けることは可能である。
makeがコンパイラ環境の一環であるのかUnixライクな環境の一部であるかの判断は難しいところだが、同じくビルドに使用するconfigureはシェルスクリプトであるためにMSYSが無ければ動作しない。また、makeの中でシェルスクリプトを使用することはかなり多いことから、実情としてはMSYS側に近い存在であるように思う。ただし、MSYS側に新しいバージョンがない等の理由でMinGW側のものをメインに使用する(プレフィックス無しのmake.exeにする)方がよい場合もある。
今回の記事で取り上げるmakeでは、バージョンは両者とも3.81で相違はないが、MSYS側のmakeの方が安定しているようだ。猫科研究所で試した限りでは、mingw32-makeは不正終了することがあった。
コンパイラ(gcc)
MinGWの核であるコンパイラを導入する。以前の猫研パックではMinGWのページからそれぞれバージョン3系と4系のGCCを導入していたが、a003からは4系のコンパイラにTwilight Dragon Mediaで配布されている、通称TDM版のGCCを導入した。また、3系と4系の混在や、未だに公式ではSJLJ方式版がメインであるため、Dwarf-2方式版は利用しない。
TDM版GCC-4に関して
TDM版のGCCには以下の特徴がある。
- より最新のGCC-4系バイナリが用意されている。
- MinGW環境向けにビルドされている。
- バグが独自に修正されていることがある。
- pthreadやiconv等がサポートされている。
MinGW公式のGCC-4は長くTechnology PreviewやAlphaの状態で、これらMinGW公式版は必ずしも安定していないため、オリジナルのGCCのバグフィックスが取り込まれた最新版を使用できることには特に意味がある。TDM版も最近まで「試験目的(experimentation purposes only)」とされていたが、有名になり多く使用されるようになったことで実用に耐えると判断され、非公式であること、無保証であることの警告付きではあるが「非クリティカルな用途に使用できる」と銘打たれた。そもそもGCCは元から無保証であるし、MinGW公式のGCC-4も不安定なのであるから、GCC-4が必要であるユーザには特段の制約ではないだろう。
TDM版の2009年6月現在の最新版であるGCC-4.4.0はオリジナルのGCCプロジェクトでも2009年4月21日にリリースされたばかりのまさに最新だ。
GCC-3
GCC-3に関しては、MinGW公式のGCC-3.4.5で特段の問題が無く、非常に安定しているため、これを使用する。オリジナルのGCCプロジェクトによるGCC-3系の最新は3.4.6だが、changesのページでも変更内容が明記されていないくらいで、GCC-3.4.5は安定バージョンと言ってよい。
SJLJ版とDwarf-2版に関して
2008年春版の今更MinGW(5)で書いているが、例外の取り扱い方式に関する違いである。Dwarf2の方が性能的には勝っているが、現在の安定版としてはSJLJ版を使用すべきだ。MinGW公式のGCCがSJLJ方式になっているため、Dwarf-2方式のGCCを導入してしまうと、GCC付属ではなく、かつバイナリで導入したライブラリ群は、その他のバイナリ(GCC付属やソースからビルドしたもの)と互換性がないことになる。
SJLJとはSetJump-LongJumpの略で、例外発生時の飛び先をsetjumpで設定する方式だ。これは予め飛び先を設定する必要があるため、try-catch構文がある度に、setjumpが実行されることになる。例外が発生しない場合、このsetjumpは単なる無駄でしかない。
一方、Dwarf2はデバッグ機能を利用して例外の飛び先を決める方式で、余計な処理を行わないために高速で動作する。しかしWindows上では、Dwarf2方式でコンパイルされていない関数のスタックフレームをクリアする必要がないと分かっている場合にしか使用できない。これはWindowsAPIのコールバック等を利用する場合に例外を発生させられないということで、コーディングに余計な注意を必要とする、ということだ。何かのライブラリをリンクする場合には、その中でも問題行動が行われていないか把握していなければならないため、現実的ではない。
このため、通常は速度を犠牲にしてSJLJ版を使用するのである。
導入
下記のファイルをそれぞれ取得しよう。
- GCC Version 3 / Current Release: gcc-3.4.5-20060117-3
- TDM's GCC/mingw32 Builds / (GCC Current Series) 4.4.0-tdm-1 (r2) Released 2009-05-02
もしAdaコンパイラやGNU製のJavaコンパイラが必要であれば、追加して構わない。
猫研パックではこれらを/_felidlabo/gccにバージョンごとにディレクトリを分けて展開し、その後.7zに再アーカイブしている。後で上書きコピーによるGCCの切り替えを可能にするため、/mingwには直接展開しない。
なお、TDM版ではない、MinGW公式のGCC4も、下記pthreadの対応が不要なだけで、同様に導入できる。
TDM版の導入に際する注意
TDM版はlibpthreadを含んでいる。pthreadとはPOSIXで規定されるスレッド機能だが、WindowsはPOSIX準拠ではないので、POSIXと同様のインターフェース(関数形式)でスレッドを制御できるようにするのがlibpthreadだ。
しかし、OSでネイティブにサポートされる機能ではないために、ライブラリで吸収しきれない差異が発生する。これはlibpthreadでもGCCでもどうしようもない制限としてユーザに降りかかる。具体的には今更MinGWの2008年春版を書いたときに併せて書いたMinGW+ffmpegのMinGW+ffmpeg(A)pthreadは複雑を読んで戴きたいが、ここではかいつまんで述べよう。
まずWindows上でlibpthreadをstaticにリンクする場合には、プロセスやスレッドの開始・終了時に、POSIXの規定にはない特別な関数を呼び出す必要がある。つまり、ソースコードレベルの互換性が無く、#ifdef等で切り分ける必要がある。この制限を避けるためにはダイナミックリンク(DLLで使用)にすればよいが、それはつまりpthread*.dllを.exeと共に配布しなければならないことを意味する。
これ自体は精神衛生的なことを除けば大きな制限ではないが、問題はconfigure等がpthreadの存在を自動的に検出し、勝手にリンクされることがあることだ。Windows環境を想定していないソフトウェアでは、staticリンク時に特別な関数を呼び出していないケースもあるため、ビルドは通るが動作時にクラッシュする事態となる。また一方、DLLをリンクするケースでは、pthreadを使用していることをユーザが把握せず、.exeのみを配布して動作しない事態に陥る。
このため猫研版では以下のファイルをリネームし、TDM版のpthreadを無効にしている。
- include/pthread.h
- include/sched.h
- include/semaphore.h
- lib/libpthread.a
- lib/libpthreadGC2-static.a
- lib/libpthreadGCE2.a
上記の注意点を承知していれば、pthreadを有効のままにしていても問題はない。
最終更新時間:2009年06月25日 15時18分36秒