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)
のコードをコンパイルせずに済みます.
- これにより,GCを使わずにメモリ管理をするようになり,
- 環境に合わせて
operator_new
等の各関数を実装する.- gccでのマングル名(
_Z12operator_newm
等)をpragma(mangle, ...)
として指定しました.関数の中身は Windows 版と同様です.
- gccでのマングル名(
"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 }
...
ビルドできたよ!引数なしならちゃんと動くよ!やったね!
早速コンパイル!
以下のプログラムをコンパイルしてみます.
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.c
と impcnvtab.c
が必要にもかかわらず makefile に記述がないため,以下のようにこれら2つもターゲットとして指定する必要があります.
$ make -f posix.mak id.c impcnvtab.c ddmd ...
また,DCにインストール済みの dmd を指定した場合でも dmd.conf は見てくれないようなので,DFLAGS等の指定は必要です.