Help us understand the problem. What is going on with this article?

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

More than 5 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等の指定は必要です.

tm_tn
Emacs とか D とかで遊ぶのが趣味です.
https://tom-tan.hatenablog.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away