D言語環境構築 2018年版


はじめに

D言語のリファレンス実装であるdmdは、インストールが簡単で、気軽に扱える言語処理系になっています。
D言語に触ってみたいと思ったときは、とりあえずdmdをインストールするのがおすすめです。

(最近GCCにD言語フロントエンドが取り込まれて、Linux等ではそちらの方が気軽に使えるようになっていくかもしれませんが……)

この記事では、dmdをインストールし、Visual Studio Codeで開発環境を構築する方法について解説します。

dmdのインストール

さっそくdmdのインストールです。D言語コンパイラのインストールは、我々D言語erの間で人生最良の行動と呼ばれているものです。

あなたも是非すぐに人生最良の行動を実践しましょう。

Linuxの場合

install.shの使用

まずは、公式のインストールスクリプトを使用するのがおすすめです。

以下のコマンドで最新安定版のdmdがユーザー個人の環境にインストールされます。ルート権限等は不要です。

$ curl -fsS https://dlang.org/install.sh | bash -s dmd

ユーザー環境を汚さないよう、インストールしてもそのままではパス等が通っていません。環境変数等をsourceすることにより、dmdが使えるようになります。

$ source $(~/dlang/install.sh dmd -a)
(dmd-X.XXX.X)$ dmd --version #dmdが使えるようになった
Copyright (C) 1999-20XX by The D Language Foundation, All Rights Reserved written by Walter Bright
(dmd-X.XXX.X)$ dub --version #dub(後述)も入っている
DUB version X.XX.X, built on XXX  X 20XX

有効になったdmdへのパスは、deactivateで元に戻せます。

(dmd-X.XXX.X)$ deactivate
$ #元にもどる

参考記事

kotetさんによる詳しい解説があります。

#dlang インストールスクリプトの使い方

パッケージマネージャを使用する

公式ダウンロードページの下の方に各ディストリビューション向けのコマンドが載っています。こちらを参考にしてみてください。

Macの場合

基本的にはLinuxの場合と同様にinstall.shが使えます。

また、公式のdmgやHomebrewパッケージも存在します。やはりこちらを参照です。

Windowsの場合

Windows Installerを使用する

公式のWindows Installerが個人的にはおすすめです。

(わざわざインストールしたくない場合は、もちろん7zで固められたパッケージも使えますが、環境変数などの設定は手動です)

ランタイムライブラリの選択

Windows版インストーラーでは、途中でVisual Studioをインストールするか、またはMinGWを使用するかの選択肢が出てきます。
これは、D言語プログラムのビルド時にC言語のランタイムライブラリおよびリンカー(64bit版)が必要になるためで、いずれかのインストールが必要になります。

Visual Studioをインストールする予定がなければ、MinGWを使用で問題ありません。

以前はWindowsで64bit実行ファイルを作成するためにはVisual Studioがどうしても必要でした。(64bit対応版のCOFF形式オブジェクト用のリンカーが必要なため)
それが最近、LLVMのリンカー(lld-link)を同梱することで不要になったとのことです。

7zファイルをダウンロードして手動で展開する

Windows Installerとは別に、実行ファイルやライブラリ一式を7z形式で圧縮したダウンロードファイルも公開されています。
こちらでは環境変数の設定が手動になりますが、より環境に影響を与えずにdmdを使用できます。
この場合は当然Visual Studioなどのインストールはされず、MinGWの使用がデフォルトになります。

ダウンロード元はWindows Installer版と同じ(7zの方を選択)です。

PATHの設定

dmdや後述するcode-dの実行に必要な設定は、環境変数PATHへのbinディレクトリの追記のみです。
msys2などを使用する場合も、@kari_techさんからコメントを頂いている通りPATHを通せば良いようです。

D言語プロジェクトをdubで作る

D言語の各種インストーラー等には、パッケージマネージャーでありビルドツールであるDUBが同梱されていて、すぐ使えるようになっています。

DUBはちょうどJavaScriptにおけるnpmのような存在です。dubコマンドを使うと、簡単にD言語プロジェクトの作成・ビルド・実行・テストが行えます。

npmのようにライブラリ等の依存関係の管理も行えます。設定ファイル(テキスト形式のdub.jsonまたはdub.sdl)に使用ライブラリとバージョンを記載しておくことで、自動的にダウンロードおよびビルド時のリンクを行ってくれます。

プロジェクトの作成

まずディレクトリを作成して、中でdub initを行います。
(install.shを使った人はsourceを忘れないでください)

すると、コンソールでプロジェクトの初期化設定について聞かれます。あとで簡単に書き換えられるので、基本的にEnter連打で問題ありません。

$ mkdir test
$ cd test
$ dub init
Package recipe format (sdl/json) [json]: #設定ファイルの形式。jsonで問題ないでしょう。
Name [test]: #プロジェクト名
Description [A minimal D application.]: #プロジェクトの説明
Author name [Cloud User]: #開発者名
License [proprietary]: #ライセンス。dmdと同じライセンスにする場合は BSL-1.0 とか
Copyright string [Copyright © 2018, D-MAN]: #著作権表記
Add dependency (leave empty to skip) []: #追加する依存ライブラリ
Successfully created an empty project in '/home/dman/test'.
Package successfully created in .

これで以下のファイルが生成されます。

$ find .
.
./source #ソースディレクトリ
./source/app.d #main関数のあるソース
./dub.json #設定ファイル。先ほどの選択内容が記載されている
./.gitignore #中間ファイル等の.gitignore

Windowsで64bit版ビルドを行いたい場合

なおWindowsでは、32bit版実行ファイルのビルドがデフォルトになってしまっています。
そのままでは、64bit版のビルドをするためにコマンドラインオプションでの指定が必要です。
(dub build --arch=x86_64といった具合です)

もし64bit版ビルドをデフォルトにしたい場合は、設定ファイルの追加を行います。

参考

以下のようなsettings.jsonを、

settings.json
{
    "defaultArchitecture": "x86_64",
    "defaultCompiler": "dmd"
}

以下のいずれかに配置します。

  • %ProgramData%\dub\settings.json
  • {dub実行ファイルのあるフォルダー}\..\etc\dub\settings.json
  • %APPDATA%\dub\settings.json

下のパスに置かれたものほど優先順位が高いです。

Windowsの64bit版ビルドでNative PDB Errorが出る場合

私の環境では以下のようなエラーが64bit版ビルドの時に発生しました。

Native PDB Error: The entry already exists.  The specified module already exists`

これは、dub.json/dub.sdllflags/nopdbを追加すると一応解消します。今後デバッガ関連で困るかもしれませんが……。

dub.json
{
    // 中略
    "lflags": ["/nopdb"] // これを追加
}

Windowsの64bit版ビルドでNOLOGO.dのエラーが出る場合

再現が行えていませんが、たまにNOLOGO.dのリンクエラーが発生するようです。
このエラーは、私の環境では再ビルド連打で直りました。

Windowsの64bitはどうもまだ鬼門ですね……。

プロジェクトの実行

自動生成されたプロジェクトはdub runですぐ動かせます。メッセージが出るだけですが……。

$ dub run
Performing "debug" build using /home/dman/dlang/dmd-X.XXX.X/linux/bin64/dmd for x86_64.
test ~master: building configuration "application"...
Linking...
Running ./test 
Edit source/app.d to start your project.

./source/app.dの中身はHelloWorldになっています。見ればすぐわかるコードです。

source/app.d
import std.stdio;

void main()
{
    writeln("Edit source/app.d to start your project.");
}

プロジェクトのテスト

D言語の気持ち良い点として、ユニットテストを書くのがすごい楽というのがあります。
なので、最初のうちからユニットテストの書き方を覚えておくととても捗ります。

unittestを書く

app.dに早速ユニットテストを追加します。

source/app.d
import std.stdio;

void main()
{
    writeln("Edit source/app.d to start your project.");
}

// 以下を追加
unittest
{
    assert(1 + 1 == 2);
}

C言語などと同様、assertの中にboolに評価される式を書きます。その式がfalseになると失敗と見なされ、テストがエラーになります。

今の所はきっと成功するはず……。

dub testで実行する

このテストはdub testコマンドで実行できます。

$ dub test
No source files found in configuration 'library'. Falling back to "dub -b unittest".
Performing "unittest" build using /home/centos/dlang/dmd-2.083.0/linux/bin64/dmd for x86_64.
test ~master: building configuration "application"...
Linking...
Running ./test 
Edit source/app.d to start your project.

先ほどと何も変わっていないのは成功した証拠です。
テストが失敗するようにしてみます。

source/app.d
unittest
{
    assert(1 + 1 == 3); //よくある間違い
}
$ dub test
No source files found in configuration 'library'. Falling back to "dub -b unittest".
Performing "unittest" build using /home/dman/dlang/dmd-X.XXX.X/linux/bin64/dmd for x86_64.
test ~master: building configuration "application"...
Linking...
Running ./test 
core.exception.AssertError@source/app.d(10): unittest failure
----------------
??:? _d_unittestp [0x43eed5]
source/app.d:10 void app.__unittest_L8_C1() [0x43dc80]
??:? void app.__modtest() [0x43e224]
??:? int core.runtime.runModuleUnitTests().__foreachbody2(object.ModuleInfo*) [0x446f17]
??:? int object.ModuleInfo.opApply(scope int delegate(object.ModuleInfo*)).__lambda2(immutable(object.ModuleInfo*)) [0x43ecde]
??:? int rt.minfo.moduleinfos_apply(scope int delegate(immutable(object.ModuleInfo*))).__foreachbody2(ref rt.sections_elf_shared.DSO) [0x44075d]
??:? int rt.sections_elf_shared.DSO.opApply(scope int delegate(ref rt.sections_elf_shared.DSO)) [0x4407ec]
??:? int rt.minfo.moduleinfos_apply(scope int delegate(immutable(object.ModuleInfo*))) [0x4406e9]
??:? int object.ModuleInfo.opApply(scope int delegate(object.ModuleInfo*)) [0x43ecb5]
??:? runModuleUnitTests [0x446ced]
??:? void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).runAll() [0x43f528]
??:? void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).tryExec(scope void delegate()) [0x43f4af]
??:? _d_run_main [0x43f417]
??:? main [0x43e249]
??:? __libc_start_main [0x361c5444]
1/1 unittests FAILED
Program exited with code 1

何か色々出てくるようになりましたね。
core.exception.AssertError@source/app.d(10): unittest failureの部分がユニットテスト失敗の箇所を指しています。

assertにメッセージを付ける

このままだとわかりにくいので、メッセージを表示させてみます。

source/app.d
unittest
{
    assert(1 + 1 == 3, "1 + 2が3にならなかった");
}
$ dub test
No source files found in configuration 'library'. Falling back to "dub -b unittest".
Performing "unittest" build using /home/dman/dlang/dmd-X.XXX.X/linux/bin64/dmd for x86_64.
test ~master: building configuration "application"...
Linking...
Running ./test 
core.exception.AssertError@source/app.d(10): 1 + 2が3にならなかった
# 後略

以上がD言語のunittestのほぼ全てです。

unittestについて、あとは、

  • ソースコードの中に何回も書ける
  • クラスや構造体の中にも書ける
  • ///unittest直前にコメントを付けると、ドキュメントツールddocで生成したドキュメントにテストコード全体が載る
    • ドキュメントのサンプルコードの記載がunittestでできる

程度のことを知っておけば大丈夫だと思います。

他の言語のユニットテストツールにあるような、綺麗な結果表示とかカッチョいいassert構文とか何も無いですが、とにかく書きやすいです。
テストをどんどん書きながら楽しくコーディングしましょう。

Visual Studio Codeを使ってみる

D言語用のIDEは何種類かあるのですが、どれも完成度という点で一抹の不安が残ります。
(そもそも、IDEが必須になるような大規模開発があまりなかったりします……)

しかし今年、code-dへのファンドが募集され、Visual Studio CodeとAtomでのサポートが改善されたようです。

私もごく少額を支援したりしたので、Visual Studio CodeでD言語を動かしてみたいと思います。

Visual Studio Codeのインストール

まずはここから普通にインストールします。

拡張機能パックのインストール

code-dを含むD言語拡張機能パックが公開されているようです。

コマンドラインで下記を実行するか、マーケットプレイスの画面で検索してインストールします。

$ code --install-extension webfreak.dlang-bundle

再起動

拡張機能を有効化するために再起動し、適当なD言語プロジェクトを開いてみると、下記のようになります。

ちゃんとシンタックスがハイライティングされたり、インテリセンス(と今どきも言うのだろうか……)されたりしますね。

確認されている問題

組み込みのタスクがうまく動かない場合がある

私のWindows環境だとなぜかバックグラウンドでdubが強制終了してしまったり、VSCodeのタスクでcode-d: dub buildできなかったりしました……。まあターミナルから直接dub runとかdub testと実行すれば何も問題ないですね!

インストールしているdubcode-ddubとのバージョン不一致

@mono_shooさんがコメントして下さった通り、一時期のdubcode-dのバージョン不一致で不具合が発生するケースがあるようです。
おそらく最新版では解消されていると思いますが、類似の事例があれば注意が必要です。
(おそらく過去バージョンのdubを再インストールするか、ビルドをcode-dだけで行う必要がある?)

まとめ

IDEの完成度がやはりまだいまいちですが、少なくとも書く分には問題なくなってきたようです。
IDE好きな人は選択肢として相対的には十分ありだと思うので、Visual Studio Codeを試してみてください!

ライセンス


この 作品 は クリエイティブ・コモンズ 表示 4.0 国際 ライセンスの下に提供されています。