GDCのビルド手順(on MSYS2)

目次

1 はじめに

GDCはGCCのD言語(本家,日本語) フロントエンドです。 2015年11月現在 github でメンテナンスが行われています。

MinGWでGDCのネイティブビルドを行ったり、Cygwin上でMinGWターゲットのクロスGDCをビルド したりしていたのですが、MSYS2でもネイティブビルド可能なようだったので手順をメモっておく 事にしました。 ここでは、(ほぼ)最新のGDC&GCCに追従すべく敢えてソースからビルドする方法を示してます。

2 前準備

コンパイラをビルドする為にMSYS2を予めインストールしておく必要があります。 MSYS2のインストールは以下のサイトを参考にさせていただきました。

MSYS2 による gcc 開発環境の構築

MSYS2のシェル環境とgcc(32bit-gccと64bit-gcc)のインストールを行います。 加えて、unzip, tar, bzip2, diffutils, make も必要です。参考サイトの 「MSYS2 関連ツールのインストール」で「patch パッケージ」をインストール している要領でインストールすればイケると思います。

3 必要なファイル

以下のアーカイブを公式ページやWebミラーなどからダウンロードしてください。

3.1 全ターゲットに共通のファイル

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」のどちらにも 共通で見えるディレクトリ(例えばホームディレクトリ以下のどこか適当な ディレクトリ)をカレントディレクトリにする事としています。

  1. unzip ~/Downloads/GDC-dadb5a3784fc9e12761e49c35937ad1c594c824d.zip
  2. xz -dc ~/Downloads/msys2_gdc_patches_151115.tar.xz | tar xf -
  3. cd GDC-dadb5a3784fc9e12761e49c35937ad1c594c824d
  4. bzip2 -dc ~/Downloads/gcc-5.2.0.tar.bz2 | tar xf -
  5. pushd gcc-5.2.0
  6. patch -p1 < ../../patches/mingw-tls-gcc-5.2.0.patch
  7. patch -p1 < ../../patches/mingw-gdc-gcc-5.2.0.patch
  8. popd
  9. patch -p0 < ../patches/mingw-gdc.patch
  10. ./setup-gcc.sh gcc-5.2.0
  11. pushd gcc-5.2.0
  12. patch -p1 < ../../patches/0001-Remove-fPIC-for-MinGW.patch
  13. popd
  14. bzip2 -dc ~/Downloads/binutils-2.23.1.tar.bz2 | tar xf -
  15. pushd binutils-2.23.1
  16. patch -p1 < ../../patches/mingw-tls-binutils-2.23.1.patch
  17. 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をビルドします。

  1. mkdir -p /mingw32/local/gdc20661_520_mingw
  2. pushd /mingw32/local/gdc20661_520_mingw
  3. /bin/cp -pr /mingw32/i686-w64-mingw32 .
  4. popd
  5. mkdir -p /mingw/include
  6. mkdir build_gcc_i686-w64
  7. pushd build_gcc_i686-w64
  8. ../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
  9. make
  10. make install
  11. popd

binutilsをビルドします。

  1. mkdir build_binutils_i686-w64
  2. pushd build_binutils_i686-w64
  3. ../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
  4. make
  5. make install
  6. 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をビルドします。

  1. mkdir -p /mingw64/local/gdc20661_520_mingw
  2. pushd /mingw64/local/gdc20661_520_mingw
  3. /bin/cp -pr /mingw64/x86_64-w64-mingw32 .
  4. popd
  5. mkdir -p /mingw/include
  6. mkdir build_gcc_x86_64-w64
  7. pushd build_gcc_x86_64-w64
  8. ../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
  9. make
  10. make install
  11. popd

binutilsをビルドします。

  1. mkdir build_binutils_x86_64-w64
  2. pushd build_binutils_x86_64-w64
  3. ../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
  4. make
  5. make install
  6. 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) を取得し、以下の手順でビルドします。

  1. gzip -dc ~/Downloads/jpegsrc.v9a.tar.gz | tar xf -
  2. mkdir -p jpeg-9a/build_i686-w64
  3. pushd jpeg-9a/build_i686-w64
  4. ../configure --target=i686-w64-mingw32 --host=i686-w64-mingw32 --build=i686-w64-mingw32 --prefix=/mingw32/local/gdc20661_520_mingw --disable-shared
  5. make
  6. make install
  7. popd

5.4 zlibライブラリのビルド

http://www.zlib.net/ よりソースアーカイブ(2015/11/15時点で zlib-1.2.8.tar.xz) を取得し、以下の手順でビルドします。

  1. xz -dc ~/Downloads/zlib-1.2.8.tar.xz | tar xf -
  2. pushd zlib-1.2.8
  3. make -fwin32/Makefile.gcc
  4. cp -p zlib.h zconf.h /mingw32/local/gdc20661_520_mingw/include/.
  5. cp -p libz.a /mingw32/local/gdc20661_520_mingw/lib/.
  6. 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実行が失敗します。

  1. xz -dc ~/Downloads/libpng-1.6.18.tar.xz | tar xf -
  2. mkdir -p libpng-1.6.18/build_i686-w64
  3. pushd libpng-1.6.18/build_i686-w64
  4. ../configure --target=i686-w64-mingw32 --host=i686-w64-mingw32 --build=i686-w64-mingw32 --prefix=/mingw32/local/gdc20661_520_mingw --disable-shared
  5. make
  6. make install
  7. 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)
    現象
    DMD2.065,2.066.1ベースのgdcをi686-*-mingw32およびx86_64-w64-mingw32ターゲットで ビルドするとstd.regex内で Segfaultする。i686-*-mingw32ではGCをdisableにすると大丈夫そう。
    対処
    std.regexに手を入れる事でワークアラウンドしています (参考1, 参考2, 参考3)
  • 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を使用するメリットは多数ありますが、デメリットも多数存在します。

  • メリット
    1. MinGW用にビルドされたライブラリが使用できる。
    2. gdbが使用できる。gdb-7.2でD言語がサポートされました。
    3. DMDよりもGDCの方がオプティマイズが効いてるらしい。
  • デメリット
    1. DMDサイトなどで書かれている例がそのまま使えない場合がある。
    2. DMD最新バージョンリリースよりも遅れる。2015年11月時点でもgithubで活発に更新されていますが、 少し離れてます(DMD2.069.1 vs GDC2.066.1)。この先も大丈夫な保証はありません。
    3. コンパイルが遅い。
    4. GDCでしか起こらない不具合がありうる。
    5. MinGWターゲットでGDCを使う人が殆ど居ない(2015年11月時点で 公式にはアルファ品質とされている)。 この為、なにやら動かなくても ある程度自力解決が求められる。

うーむ、やっぱりデメリットの方が多いなぁ(^^; まぁ、「そこに山があるから」という事で。

8 履歴

  2015/11/15 : 初版(「MinGWターゲットのクロスGDCをCygwinでビルド」からfork)。
  2016/03/26 : 誤記修正。

TOP PREV

著者: TANE

Emacs 24.5.1 (Org mode 8.2.10)