Posted at
D言語Day 9

D言語で書かれたD言語コンパイラー・DDMDをビルドしてみる (挫折編)

More than 3 years have passed since last update.

D言語 Advent Calendar 2014の9日目の記事です.


DDMD?

現在,D言語のリファレンス実装である dmd は,C++で書かれています.

これに対し,ddmd はD言語で書かれたDコンパイラーなのですが,まだdmd のリポジトリには含まれておりません.

これを解決する Pull Request がIssue3410で,これがマージされれば, dmd と ddmd の両方を公式のリポジトリからビルドできるようになります.


この記事では

一足先に ddmd を体験するために,ddmd をビルドする方法を解説します解説しようと思っていましたが,ビルドできませんでした!

なのでここでは,ddmd をビルドする際の注意点や試してみたことを列挙します.

ddmd にチャレンジする際のヒントになれば幸いです.

これ以降は,次の環境での試行錯誤の結果です.


  • Arch Linux (64bit)

  • gcc 4.9.2

  • druntime/Phobosのバージョン: trunk


ビルド方法 (試行錯誤含む)

ddmd は,D言語のコミッターのDaniel Murphyさんのリポジトリで公開されています.

ddmd の開発ブランチは newmagic です.

$ git clone https://github.com/yebblies/dmd.git

$ cd dmd
dmd $ git co newmagic
dmd $ git log -n 1
commit e4445baf3c4571fc5d2b99e28057b0605e8a8ed1
Author: Daniel Murphy <yebblies@gmail.com>
Date: Sat Nov 8 19:45:37 2014 +1100

enable gc by default

Issue3410の説明には,「make ddmd でビルドできるよ!」と書いてありますが,自分の環境ではいくつかの問題に遭遇しました.以下は遭遇した順です.


object.d を読んでくれない

dmd $ cd src

dmd/src $ make -f posix.mak ddmd
...
./dmd -m64 -ofmagicport/magicport2 magicport/magicport2.d magicport/ast.d magicport/scanner.d magicport/tokens.d magicport/parser.d magicport/dprinter.d magicport/typenames.d magicport/visitor.d magicport/namer.d
Error: cannot find source code for runtime library file 'object.d'
dmd might not be correctly installed. Run 'dmd -man' for installation instructions.
config file: /home/tm_tn/.denv/shims/dmd.conf
Specify path to file 'object.d' with -I switch
posix.mak:481: ターゲット 'magicport/magicport2' のレシピで失敗しました
make: *** [magicport/magicport2] エラー 1

これは ddmd をビルドするための dmd が, dmd.conf の内容を読んでくれないのが原因です.

dmd.conf をリポジトリ内にコピーしても読まないため,環境変数 DFLAGS と MODEL_FLAG をしていすることで解決しました(MODEL_FLAGを指定しないと libphobos2 のリンクに失敗します).


"Error: static assert(0) is false"

/path/to/foo は foo のあるディレクトリの場所を表しています. 環境に応じて変更してください.

dmd/src $ make -f posix.mak ddmd DFLAGS="-I/path/to/phobos -I/path/to/druntime/import -L-L/path/to/lib64 -L--export-dynamic" MODEL_FLAG=-L-L/path/to/lib64

...
root/rmem.d(54): Error: static assert (0) is false
posix.mak:519: ターゲット 'ddmd' のレシピで失敗しました
make: *** [ddmd] エラー 1

非Windows環境では, root/rmem.d に含まれる static assert に引っかかるためビルドできません.

これを解決するために以下の3パターンを試してみましたが,結果はどれも同じでした…



  • static assert(0) の行をコメントアウトする.

  • root/rmem.d の6行目のversion=GC; をコメントアウトする.


    • これにより,GCを使わずにメモリ管理をするようになり,static assert(0)のコードをコンパイルせずに済みます.



  • 環境に合わせて operator_new 等の各関数を実装する.


    • gccでのマングル名(_Z12operator_newm等)をpragma(mangle, ...) として指定しました.関数の中身は Windows 版と同様です.




"Error: variable p is shadowing variable..."

dmd/src $ make -f posix.mak ddmd DFLAGS="-I/path/to/phobos -I/path/to/druntime/import -L-L/path/to/lib64 -L--export-dynamic" MODEL_FLAG=-L-L/path/to/lib64

...
cppmangle.d(332): Error: variable p is shadowing variable cppmangle.CppMangleVisitor.cpp_mangle_name.p
posix.mak:519: ターゲット 'ddmd' のレシピで失敗しました
make: *** [ddmd] エラー 1

これはそのままですね.該当箇所のスコープで使われている p を,別の名前に置き換えました.


ddmd のバイナリ生成はできた!

dmd/src $ make -f posix.mak ddmd DFLAGS="-I/path/to/phobos -I/path/to/druntime/import -L-L/path/to/lib64 -L--export-dynamic" MODEL_FLAG=-L-L/path/to/lib64

...
dmd/src $ ls ddmd
ddmd
dmd/src $ ./ddmd
DMD v2.067 DEBUG
DMD64 D Compiler v2.067
Copyright (c) 1999-2014 by Digital Mars written by Walter Bright
Documentation: http://dlang.org/
Config file: (null)
Usage:
dmd files.d ... { -switch }
...

ビルドできたよ!引数なしならちゃんと動くよ!やったね!


早速コンパイル!

以下のプログラムをコンパイルしてみます.


sample.d

module sample;

import std.stdio;

void main() {
writeln("Hello!");
}


dmd/src $ cp ddmd ~

dmd/src $ cd
$ cat dmd.conf
[Environment64]
DFLAGS=-I/path/to/phobos -I/path/to/druntime/import -L-L/path/to/lib64 -L--export-dynamic
$ ./ddmd sample.d
DMD v2.067 DEBUG
zsh: segmentation fault (core dumped) ./ddmd sample.d

おや?


どこがおかしいのか

GDBを使って調べると, root.rmem.Mem.realloc 辺りでこけている様子.

ちゃんとコードを読まないと解決は難しそう.


終わりに

後は偉い人達に任せました!ビルドできたら記事書いてくれると私が喜びます!


おまけ


Q. DDMDってフルスクラッチで書かれてるの?

A. 違うよ. ビルド時に,C++ で書かれた dmd のソースをD言語に変換してるよ.

make ddmd のビルドプロセスは,大まかには:


  • C++のソースをD言語に変換するツール magicport/magicport2 のビルド


  • magicport/magicport2 を使って dmd のソースをD言語に変換 (root/rmem.d等の一部例外あり)

  • 変換したD言語のソースをビルドして ddmd を生成

という大変ロマンにあふれた構成になっています.


Q. ddmdのビルドに,インストール済みの dmd は使えないの?

A. 環境変数 DC に,インストール済みの dmd を設定すればそちらを使ってくれます.

注意点としては, ddmd のビルドに id.cimpcnvtab.c が必要にもかかわらず makefile に記述がないため,以下のようにこれら2つもターゲットとして指定する必要があります.

$ make -f posix.mak id.c impcnvtab.c ddmd ...

また,DCにインストール済みの dmd を指定した場合でも dmd.conf は見てくれないようなので,DFLAGS等の指定は必要です.