GDCのビルド手順(on MSYS2)
1 はじめに
2 前準備
コンパイラをビルドする為にMSYS2を予めインストールしておく必要があります。 MSYS2のインストールは以下のサイトを参考にさせていただきました。
MSYS2のシェル環境とgcc(32bit-gccと64bit-gcc)のインストールを行います。 加えて、unzip, tar, bzip2, diffutils, make も必要です。参考サイトの 「MSYS2 関連ツールのインストール」で「patch パッケージ」をインストール している要領でインストールすればイケると思います。
3 必要なファイル
以下のアーカイブを公式ページやWebミラーなどからダウンロードしてください。
3.1 全ターゲットに共通のファイル
- gcc-5.2.0.tar.bz2 : GCCのソース一式
- GDC-dadb5a3784fc9e12761e49c35937ad1c594c824d.zip : GDCのソース一式(ページの Download ZIPボタンから取得)
- binutils-2.23.1.tar.bz2 : TLSパッチの当たるバージョン2.23.1の binutilsソース一式
- msys2_gdc_patches_151115.tar.xz : MSYS2向け不具合解消パッチ群
3.2 使用するGDCのソースについて
GCCは実際にビルドして特に問題の無かった バージョン5.2.0 を使用しています。 GDCのソースアーカイブはgithubのGDCページからダウンロードします。 ただし、masterブランチはgcc-6向けにメンテナンスされていますので、 gdc-5のブランチからソースを取得します。 ソースの取得方法は色々ありますが、TANEは Network から取得する方法を使用しています。 gdc-5の線から任意のバージョンを選択して画面移動、「Browse files」ボタンを 押して更に画面移動し、「Download ZIP」ボタンでソース一式を取得します。
2015年11月時点では、MinGW向けはアルファ品質という位置付けの為、 必ずしも最新のソースが万事問題無しという訳ではありません。この為、 本ページでは、ビルド&実行がうまくできたバージョンで説明しています。
4 GDCのビルド手順
4.1 GDCソースの展開とセットアップ
まずはGDCのソース本体を展開し、パッチを適用します。 アーカイブ群は ~/Downloads の下に、ビルドはカレントディレクトリで行うものとします。 「MinGW-w64 Win32 Shell」と「MinGW-w64 Win64 Shell」のどちらにも 共通で見えるディレクトリ(例えばホームディレクトリ以下のどこか適当な ディレクトリ)をカレントディレクトリにする事としています。
unzip ~/Downloads/GDC-dadb5a3784fc9e12761e49c35937ad1c594c824d.zip
xz -dc ~/Downloads/msys2_gdc_patches_151115.tar.xz | tar xf -
cd GDC-dadb5a3784fc9e12761e49c35937ad1c594c824d
bzip2 -dc ~/Downloads/gcc-5.2.0.tar.bz2 | tar xf -
pushd gcc-5.2.0
patch -p1 < ../../patches/mingw-tls-gcc-5.2.0.patch
patch -p1 < ../../patches/mingw-gdc-gcc-5.2.0.patch
popd
patch -p0 < ../patches/mingw-gdc.patch
./setup-gcc.sh gcc-5.2.0
pushd gcc-5.2.0
patch -p1 < ../../patches/0001-Remove-fPIC-for-MinGW.patch
popd
bzip2 -dc ~/Downloads/binutils-2.23.1.tar.bz2 | tar xf -
pushd binutils-2.23.1
patch -p1 < ../../patches/mingw-tls-binutils-2.23.1.patch
popd
以降、必要なターゲットについてビルドしていきます。
メモ: 「MinGWターゲットのクロスGDCをCygwinでビルド」とほぼ同じパッチを使用していますが、MSYS2のlnコマンドはファイルコピーで代用されているようなので、パッチを当てる実行順番が少し面倒になってます。
4.2 MINGW32(i686-w64-mingw32)でビルド
「MinGW-w64 Win32 Shell」で起動したターミナルで実行します。
例では /mingw32/local/gdc20661_520_mingw にインストールするものとしてビルドします。 ビルドは「GDC-ソースの展開とセットアップ」を実行した直後をカレントディレクトリ (GDC-*ディレクトリの中)とします。 もし本ターゲットのコンパイラが必要無ければビルドの必要はありません。
留意点: 一般的には 先にbinutilsをビルドしてからgcc/gdcをビルドするものなのですが、gdcがリンクに失敗する問題に対処する為にgcc/gdcを先にビルドします。
gccとgdcをビルドします。
mkdir -p /mingw32/local/gdc20661_520_mingw
pushd /mingw32/local/gdc20661_520_mingw
/bin/cp -pr /mingw32/i686-w64-mingw32 .
popd
mkdir -p /mingw/include
mkdir build_gcc_i686-w64
pushd build_gcc_i686-w64
../gcc-5.2.0/configure --with-pkgversion=gdc-5" dadb5a3784" --build=i686-w64-mingw32 --host=i686-w64-mingw32 --target=i686-w64-mingw32 --enable-languages=c,d --prefix=/mingw32/local/gdc20661_520_mingw --enable-__cxa_atexit --disable-libmudflap --disable-libgomp --disable-libssp --disable-libquadmath --disable-libquadmath-support --disable-libsanitizer --enable-threads=win32 --disable-win32-registry --enable-target-optspace --disable-nls --disable-bootstrap --disable-shared --disable-multilib --enable-long-long
make
make install
popd
binutilsをビルドします。
mkdir build_binutils_i686-w64
pushd build_binutils_i686-w64
../binutils-2.23.1/configure --build=i686-w64-mingw32 --host=i686-w64-mingw32 --target=i686-w64-mingw32 --with-arch=i686 --prefix=/mingw32/local/gdc20661_520_mingw --disable-nls --disable-win32-registry --disable-werror
make
make install
popd
以上で、/mingw32/local/gdc20661_520_mingwにパスを通せばgdcコンパイラが使用できます。
$ export PATH="/mingw32/local/gdc20661_520_mingw/bin:$PATH" $ gdc -v Using built-in specs. COLLECT_GCC=C:\msys64\mingw32\local\gdc20661_520_mingw\bin\gdc.exe COLLECT_LTO_WRAPPER=c:/msys64/mingw32/local/gdc20661_520_mingw/bin/../libexec/gcc/i686-w64-mingw32/5.2.0/lto-wrapper.exe Target: i686-w64-mingw32 Configured with: ../gcc-5.2.0/configure --with-pkgversion='gdc-5 dadb5a3784' --build=i686-w64-mingw32 --host=i686-w64-mingw32 --target=i686-w64-mingw32 --enable-languages=c,d --prefix=/mingw32/local/gdc20661_520_mingw --enable-__cxa_atexit --disable-libmudflap --disable-libgomp --disable-libssp --disable-libquadmath --disable-libquadmath-support --disable-libsanitizer --enable-threads=win32 --disable-win32-registry --enable-target-optspace --disable-nls --disable-bootstrap --disable-shared --disable-multilib --enable-long-long Thread model: win32 gcc version 5.2.0 (gdc-5 dadb5a3784)
4.3 MINGW64(x86_64-w64-mingw32)でビルド
「MinGW-w64 Win64 Shell」で起動したターミナルで実行します。
例では /mingw64/local/gdc20661_520_mingw にインストールするものとしてビルドします。 ビルドは「GDC-ソースの展開とセットアップ」を実行した直後をカレントディレクトリ (GDC-*ディレクトリの中)とします。 もし本ターゲットのコンパイラが必要無ければビルドの必要はありません。
留意点: 一般的には 先にbinutilsをビルドしてからgcc/gdcをビルドするものなのですが、gdcがリンクに失敗する問題に対処する為にgcc/gdcを先にビルドします。
gccとgdcをビルドします。
mkdir -p /mingw64/local/gdc20661_520_mingw
pushd /mingw64/local/gdc20661_520_mingw
/bin/cp -pr /mingw64/x86_64-w64-mingw32 .
popd
mkdir -p /mingw/include
mkdir build_gcc_x86_64-w64
pushd build_gcc_x86_64-w64
../gcc-5.2.0/configure --with-pkgversion=gdc-5" dadb5a3784" --build=x86_64-w64-mingw32 --host=x86_64-w64-mingw32 --target=x86_64-w64-mingw32 --enable-languages=c,d --prefix=/mingw64/local/gdc20661_520_mingw --enable-__cxa_atexit --disable-libmudflap --disable-libgomp --disable-libssp --disable-libquadmath --disable-libquadmath-support --disable-libsanitizer --enable-threads=win32 --disable-win32-registry --enable-target-optspace --disable-nls --disable-bootstrap --disable-shared --disable-multilib --enable-long-long
make
make install
popd
binutilsをビルドします。
mkdir build_binutils_x86_64-w64
pushd build_binutils_x86_64-w64
../binutils-2.23.1/configure --build=x86_64-w64-mingw32 --host=x86_64-w64-mingw32 --target=x86_64-w64-mingw32 --prefix=/mingw64/local/gdc20661_520_mingw --disable-nls --disable-win32-registry --disable-werror
make
make install
popd
以上で、/mingw64/local/gdc20661_520_mingw/binにパスを通せばgdcコンパイラが使用できます。
$ export PATH="/mingw64/local/gdc20661_520_mingw/bin:$PATH" $ gdc -v Using built-in specs. COLLECT_GCC=C:\msys64\mingw64\local\gdc20661_520_mingw\bin\gdc.exe COLLECT_LTO_WRAPPER=c:/msys64/mingw64/local/gdc20661_520_mingw/bin/../libexec/gcc/x86_64-w64-mingw32/5.2.0/lto-wrapper.exe Target: x86_64-w64-mingw32 Configured with: ../gcc-5.2.0/configure --with-pkgversion='gdc-5 dadb5a3784' --build=x86_64-w64-mingw32 --host=x86_64-w64-mingw32 --target=x86_64-w64-mingw32 --enable-languages=c,d --prefix=/mingw64/local/gdc20661_520_mingw --enable-__cxa_atexit --disable-libmudflap --disable-libgomp --disable-libssp --disable-libquadmath --disable-libquadmath-support --disable-libsanitizer --enable-threads=win32 --disable-win32-registry --enable-target-optspace --disable-nls --disable-bootstrap --disable-shared --disable-multilib --enable-long-long Thread model: win32 gcc version 5.2.0 (gdc-5 dadb5a3784)
5 外部ライブラリのビルド
全てD言語で書かれたプログラムでは必要ありませんが、画像などを扱う場合は 既存のC言語で書かれたライブラリを利用するのが便利な場合があります。 ここではCコンパイラを使用してライブラリをビルドする例をいくつか示します。
5.1 ライブラリの使用にあたって
外部ライブラリを使用する際、MinGWのGDCでは 明にスタティックリンク指示しないと 動かない実行ファイルが生成される場合があります。 スタティックリンクするには -static オプションをコンパイラ引数に加えてみてください。
gdc -static ....
5.2 前準備
「MinGW-w64 Win32 Shell」および「MinGW-w64 Win64 Shell」毎にビルドする必要があります。 ビルドする際にはターゲット用のコンパイラが使用できるように予めPATHを通しておきます。
本項の説明では 「MinGW-w64 Win32 Shell」で起動したターミナルで実行する MINGW32(i686-w64-mingw32)環境を例にしています。 また、/mingw32/local/gdc20661_520_mingwにインストールするものとし、ソースアーカイブは ~/Downloads の下に置いてあるものとしています。
注意点: prefix指定には十分注意してください。インストール先の /mingw32と/mingw64を 間違えると開発環境を破壊する恐れがあります。
5.3 JPEGライブラリのビルド
http://www.ijg.org/ よりソースアーカイブ(2015/11/15時点で jpegsrc.v9a.tar.gz) を取得し、以下の手順でビルドします。
gzip -dc ~/Downloads/jpegsrc.v9a.tar.gz | tar xf -
mkdir -p jpeg-9a/build_i686-w64
pushd jpeg-9a/build_i686-w64
../configure --target=i686-w64-mingw32 --host=i686-w64-mingw32 --build=i686-w64-mingw32 --prefix=/mingw32/local/gdc20661_520_mingw --disable-shared
make
make install
popd
5.4 zlibライブラリのビルド
http://www.zlib.net/ よりソースアーカイブ(2015/11/15時点で zlib-1.2.8.tar.xz) を取得し、以下の手順でビルドします。
xz -dc ~/Downloads/zlib-1.2.8.tar.xz | tar xf -
pushd zlib-1.2.8
make -fwin32/Makefile.gcc
cp -p zlib.h zconf.h /mingw32/local/gdc20661_520_mingw/include/.
cp -p libz.a /mingw32/local/gdc20661_520_mingw/lib/.
popd
gdcのビルド時に一緒にビルドしたbinutilsのstripコマンドを使うと zlib1.dllのstrip実行に失敗するようです(もう一度make実行すると 通りますがzlib1.dllは stripされていない事になっているでしょう)。gdcではスタティックライブラリがあれば良いので ひとまず問題はありません。 また、ヘッダファイルとスタティックライブラリを手動コピーしてインストールしています。
5.5 PNGライブラリのビルド
http://www.libpng.org/pub/png/ よりソースアーカイブ (2015/11/15時点で libpng-1.6.18.tar.xz)を取得し、以下の手順でビルドします。
予め zlibライブラリをビルド&インストールしておく必要があります。インストールされていないと configure実行が失敗します。
xz -dc ~/Downloads/libpng-1.6.18.tar.xz | tar xf -
mkdir -p libpng-1.6.18/build_i686-w64
pushd libpng-1.6.18/build_i686-w64
../configure --target=i686-w64-mingw32 --host=i686-w64-mingw32 --build=i686-w64-mingw32 --prefix=/mingw32/local/gdc20661_520_mingw --disable-shared
make
make install
popd
6 不具合とパッチについて
「MinGWターゲットのクロスGDCをCygwinでビルド」 のパッチとほぼ同じですが、説明はMSYS2ネイティブコンパイラに関するものだけ行います。
6.1 ビルド時の問題
- venix1さんのパッチ がいくつか必要。
- 現象
- gdc-2.05x時代に venix1さんが作成したパッチが無いと、コンパイラのビルドに失敗する、 生成したコンパイラでTLS関連シンボルが見つからないなどの現象が発生する。
- 対処
- gcc-4.x.x向けだったパッチを5.x.x向けに再作成して対応しています。 (0001-Remove-fPIC-for-MinGW.patch, mingw-tls-gcc-5.2.0.patchの一部, mingw-tls-binutils-2.23.1.patch)
6.2 コンパイラおよびライブラリの問題
- メソッド/構造体メンバー関数呼び出しにfastcallコードが生成される
- 現象
- gdcをi686-*-mingw32ターゲットでビルドすると、メソッド/構造体メンバー関数呼び出しに fastcallコードが生成されて連想配列アクセスで Segfaultする。
- 対処
- gcc/config/i386/i386.cに手を入れる事でワークアラウンドしています (参考)
- std.regex内で Segfaultする(その1)
- std.regex内で Segfaultする(その2)
- 現象
- DMD2.065,2.066.1ベースのgdcをi686-*-mingw32ターゲットでビルドするとstd.regex内で Segfaultする。
- 対処
- std.functionalに手を入れる事でワークアラウンドしています (参考)
- リンク時にcurl.o内でcore.sys.posix.sys.socketが見つからなくてエラー
- 現象
- libphobos/src/etc/c/curl.dで無条件に「import core.sys.posix.sys.socket;」 されているが、 Windowsターゲットだとリンク時に 「undefined reference to `_D4core3sys5posix3sys6socket12__ModuleInfoZ'」 でリンクに失敗する。
- 対処
- libphobos/src/etc/c/curl.d内で無条件に「import core.sys.posix.sys.socket;」している のをコメントアウトしています。
- x86_64-w64-mingw32ターゲットのgdcでコンパイルした場合に format()でreal型を指定するとSegfault(150913追加)
- 現象
- x86_64-w64-mingw32ターゲットのgdcで
writef("%f",PI);
のようにreal型をformat()(writef()内で使用)の 引数に指定するコードをコンパイル&実行すると __mingw_pformat() 内でSegfaultが発生します (参考)。 - 対処
writef("%f",cast(double)(PI));
のようにdouble型にキャストする事で回避できます (パッチによる対処ではありません。コーディングによる対処が必要です)。 厳密にreal型で表示したい場合のワークアラウンドにはなりません......
6.3 その他
- libphobos/src/std/socket.d内の関数シンボルが見つけられずリンクに失敗してしまう場合がある
- 現象
- i686-w64-mingw32 および x86_64-w64-mingw32 ターゲットのgdcを使用すると 明示的に「-lgphobos2 -lws2_32」を指定しないと libphobos/src/std/socket.d内の 関数シンボルが見つけられずリンクに失敗してしまう場合がある。
- 対処
- Cygwinでビルドしたgdcクロスコンパイラで発生した問題ですが、MSYS2でも同じだったため binutilsをビルドするという同様の対処を行っています。ただし、コンパイラを先にビルド してからbinutilsをビルドするという、一般的な方法と逆の手順を踏む必要がありました。 ただ、これで何故うまくいくのか理由は判っていません。
7 その他
本家のdmdコンパイラはバグの再現性確認程度にしか使用した事がありません。 ライブラリやツールの事が良くわからないからというのが理由です(^^; GDCを使用するメリットは多数ありますが、デメリットも多数存在します。
- メリット
- MinGW用にビルドされたライブラリが使用できる。
- gdbが使用できる。gdb-7.2でD言語がサポートされました。
- DMDよりもGDCの方がオプティマイズが効いてるらしい。
- デメリット
- DMDサイトなどで書かれている例がそのまま使えない場合がある。
- DMD最新バージョンリリースよりも遅れる。2015年11月時点でもgithubで活発に更新されていますが、 少し離れてます(DMD2.069.1 vs GDC2.066.1)。この先も大丈夫な保証はありません。
- コンパイルが遅い。
- GDCでしか起こらない不具合がありうる。
- MinGWターゲットでGDCを使う人が殆ど居ない(2015年11月時点で 公式にはアルファ品質とされている)。 この為、なにやら動かなくても ある程度自力解決が求められる。
うーむ、やっぱりデメリットの方が多いなぁ(^^; まぁ、「そこに山があるから」という事で。