2015/07/02

Debian/Ubuntuでmingw-w64を用いてWindows向けのプログラムをコンパイルする

Windows上で動作する実行形式は基本的にはWindows上でビルドされるが、GNU/Linux上でMinGWと呼ばれるツール群のクロスコンパイラを用いてビルドすることもできる。

ここではDebian/Ubuntuで簡単に導入可能なパッケージを用いたコンパイル作業についてを扱う。他のディストリでも同様のパッケージが提供される場合があるが、コマンド名や一部ファイルの配置場所が異なる可能性がある。

本記事で扱うパッケージでインストールされるのは本家MinGWではなく、2007年にWin64や追加APIのサポートを目的として派生した “mingw-w64” と呼ばれるプロジェクトが配布しているバージョンとなる。 “w64” と付いているが、Win64専用というわけではなく、Win32にも対応している。

  1. インストールするためのメタパッケージ
  2. 各コンパイラのコマンド名
  3. C++言語などのコンパイラ使用時の注意点
    1. GCCランタイムライブラリのライセンスの扱いについて

インストールするためのメタパッケージ

プロジェクト名でもある “mingw-w64” という名前のパッケージを選択してインストールすることで、Win32とWin64のどちらのアーキテクチャの実行形式も作成できるようになる。Windows API(DirectX含む)についての開発ファイルもインストールされる。

プログラミング言語のサポートについては基本的にC言語とC++言語のみとなるが、AdaとFortranの2つ[1]については推奨パッケージとして同時にインストールされる場合がある。

Objective-C系のサポートについては

  • gobjc-mingw-w64 (Objective-C)
  • gobjc++-mingw-w64 (Objective-C++)

パッケージを別途選択・インストールすることで対応できる。

各コンパイラのコマンド名

以下の表に各コンパイラのコマンド名をまとめている。

(x86_32やx86_64のアーキテクチャにおける)GNU/LinuxのGCCでは-m32-m64といったオプションで出力ファイルの “x86_32向けかx86_64向けか” を指定することができるが、このパッケージ群では(そうした仕組みではなく)コマンド名によって対象のアーキテクチャが決まる。

コマンド名対象言語出力
x86_64-w64-mingw32-gccCWin64
x86_64-w64-mingw32-g++C++
x86_64-w64-mingw32-gnatAda
x86_64-w64-mingw32-gfortranFortran
x86_64-w64-mingw32-windresリソース
i686-w64-mingw32-gccCWin32
i686-w64-mingw32-g++C++
i686-w64-mingw32-gnatAda
i686-w64-mingw32-gfortranFortran
i686-w64-mingw32-windresリソース

コマンド名の最初の部分が対象アーキテクチャを示し、"w64-mingw32" の後ろの部分は(クロスコンパイラではない、通常の)GCCと同様に対象言語を示している。

各コマンドは末尾に “-posix” が付いたものと “-win32” が付いたものが存在し、前者はスレッドにpthreadが使用できるもので後者はWindows APIのスレッド機能を用いるものとなる。速度に関しては後者のほうが高速とされる。末尾なしのコマンド(上の表に示したもの)はシンボリックリンクとなっており、手元のUbuntu 15.04では “-win32” が付いたほうを指し示している(変更可)。

mingw-w64 3.2.0時点ではpthread版のコンパイラが出力した実行ファイルは動作時にlibwinpthread-1.dllに依存する。libwinpthread-1.dllは以下の場所にあるので、ここから実行ファイルのあるディレクトリなどにコピーする必要がある。

  • Win64版: /usr/x86_64-w64-mingw32/lib/
  • Win32版: /usr/i686-w64-mingw32/lib/

この “winpthreads” ライブラリはMITライセンスと一部に修正(三条項)BSDライセンスが使用されており、制約は少ない。

C++言語などのコンパイラ使用時の注意点

C++コンパイラでコンパイル処理を行った実行ファイルはGCC 4.9系時点では以下のDLL(ランタイムライブラリの類)に依存する。

  • libstdc++-6.dll
  • libgcc_s_seh-1.dll

これらのファイルは

  • Win64 + pthread版: /usr/lib/gcc/x86_64-w64-mingw32/4.9-posix/
  • Win64 + Winスレッド版: /usr/lib/gcc/x86_64-w64-mingw32/4.9-win32/
  • Win32 + pthread版: /usr/lib/gcc/i686-w64-mingw32/4.9-posix/
  • Win32 + Winスレッド版: /usr/lib/gcc/i686-w64-mingw32/4.9-win32/

に存在するので、コンパイラが出力した実行ファイルのあるディレクトリなどにコピーする。その際、 “posix” と “win32” のDLLは混ぜないように注意する。

他の言語でも、例えばFortranの場合は前述のディレクトリ内の

  • libgfortran-3.dll
  • libquadmath-0.dll[2]
  • libgcc_s_seh-1.dll

が必要になる。

こうしたDLLをコピーする代わりにライブラリを静的リンクする(埋め込む)方法もあり、C++言語の場合はリンク時に “-static-libstdc++ -static-libgcc” オプションを付ける。

Fortran(でlibquadmath-0.dllが必要な場合)では “-static-libgfortran -static-libgcc -static-libquadmath” というオプションを付けたいところだが静的リンクするためのオプションは利用できない

ただ、同URLの記述を参考に

$ x86_64-w64-mingw32-gcc test.f95 -o test.exe -static-libgcc -Wl,-Bstatic -lgfortran -lquadmath -Wl,-Bdynamic -lm

のようにして静的リンクすることはできる。

GCCランタイムライブラリのライセンスの扱いについて

GCC関係のランタイムライブラリ(GCCが生成した機械語形式のファイルが自動的に依存するもの)の使用については、コンパイルされるプログラムのライセンスに関わらずGCCランタイムライブラリ例外によって許可されている。

コンパイル時にGCCがどのように利用されたかが条件として関わってくる点には注意が必要だが、GCCに含まれるコンパイラをそのまま用いている分には問題はない。

[引用]GCCランタイムライブラリ例外とFAQ(日本語訳)
GCCに付属するあるライブラリのライセンスはまだ変更されていません。これらのライブラリはGCCが生成するオブジェクトコードによって自動的に使われます。そのため、これらのライブラリが単にGPLの条項だけで配布された場合、GCCが生成するすべてのオブジェクトコードが同じ条項で配布されなければならないでしょう。しかし、FSFは、開発者がGCCのライブラリを、どのようなプログラムに対しても、そのライセンスにかかわらず使うことを許すことを、だいぶ前に決めました。(中略)GCCランタイムライブラリ例外がカバーするのは、そのライセンスヘッダに例外が適用されると述べられた告知があるすべてのファイルです。これには、libgcc, libstdc++, libfortran, libgomp, libdecnumber, libgcov とGCCで配布されるそのほかのライブラリが含まれます。

ただしlibquadmath[3]についてはLGPLライセンスとなっており、ランタイムライブラリ例外についての記述もないため、configureスクリプトに--disable-libquadmath-supportオプション[4]を付けずにビルドされた[5]GCCでFortranのプログラムをコンパイルする場合、出力された機械語ファイルはLGPLライセンスのライブラリにリンクしていることになるため、同ライセンスの制約を受ける(将来同ライブラリのライセンスが変更されれば制約はなくなると思われる)。

使用したバージョン:
  • mingw-w64 3.2.0
  • GCC 4.9.2
[1]: それぞれパッケージ名は “gnat-mingw-w64” と “gfortran-mingw-w64”
[2]: クロスコンパイラのGCCにおける本ライブラリのサポートが無効になっていれば必要ないが、Debian/Ubuntuのパッケージでは有効になっている
[3]: 4倍精度浮動小数点数を扱う機能を提供するライブラリ
[4]: 説明文は “disable libquadmath support for Fortran”
[5]: つまり同ライブラリのサポートが “有り” の