VisualStudioCodeでD言語を使う

# はじめに
この前、D言語を布教する機会がありました。
業務中に自分がD言語で作った業務支援的なトイプログラムを改造したいというのです。
あっハイと言ってソースコードを渡しただけですべて察して、自分で調べてうまいことしてくれるならその人はかなり訓練された人ですが、だれもがそうできるわけではありません。というか、仕事仲間に塩対応して無駄に時間を使わせるのも忍びないし、せっかくの布教機会なので、開発環境を整えるところまでお手伝い。
さて、最速で開発環境を整えるにはどうしたらいいでしょうか。

- dmdのインストール
- VisualStudioCodeのインストール
- VisualStudioCodeの拡張機能のインストール
- VisualStudioCodeの環境設定
- ビルドの仕方
- デバッグの仕方

なお、今回の解説はWindowsが前提となっています。それ以外の環境は適宜読みかえてください。


# dmdのインストール
[公式ダウンロードページ](https://dlang.org/download.html#dmd)から、環境にあったバージョンをインストールします。
管理者権限使えるならインストーラから、そうじゃないなら7-zipでいいでしょう。
この場合の詳しいインストール方法は、別の解説サイトを探してください。[公式でも解説してますね。](https://tour.dlang.org/tour/ja/welcome/install-d-locally)

さらに言えば、既存の環境があれば、それをそのまま使うのでもいいです。ただし、その場合はsc.iniの内容は注意しましょう。
64bitバイナリや32bit-mscoffのライブラリをコンパイルしたい場合はWindowsSDKのインストール先とかバージョンとか要チェックです。

公式のインストーラや7-zipを使う場合で、dubでビルドできない静的ライブラリがある場合は、これもビルドします(自分の場合これが面倒なので自分の環境をそのまま渡しました)。

今回はVisualStudioCodeを使うので、別にここでパスを通す必要はないですが、通っていると楽です。

あと、インストール先はあまりパスが深くなるような場所にするのはオススメしません。日本語や空白交じりのパスになるのも避けるのがいいでしょう。
そういうことをするのは、よくわからないリンクエラーとか、謎のコンパイルエラーとか、なぜかビルドできないってなっても自分で原因調べて対処して、ついでに[Bugzilla](https://issues.dlang.org/)とかに報告できたりする人だけにしましょう。

# VisualStudioCodeのインストール
[公式ダウンロードページ](https://code.visualstudio.com/download)から、環境にあったバージョンをインストールします。
管理者権限使えるならインストーラから、そうじゃないならZIPでいいでしょう。
詳しいインストール手順は別のところでさんざん解説されてますし、特に迷うこともないので省略します。
今回の例では、ZIP解凍でやることにします。(管理者権限不要なので)

あえて言えば、VisualStudioCodeで、dmdにパスが通っているといいです。パスが通ってなくても設定で何とかなるかもしれませんが、変なところで躓きそうなのでお勧めしません。以下のような起動スクリプト(バッチファイル)を書くと楽です。

## 起動スクリプトを書く場合
dmdにパスを通すには以下のようにします。
ちなみに、以下はdmdを`C:\app\dmd\`以下にいれたり、VSCodeをZIPから解凍して`C:\app\VisualStudioCode\`にいれたりしています。

```bat:vscode.bat
@PATH=C:\app\dmd\windows\bin;%PATH%
@start C:\app\VisualStudioCode\Code.exe
```


## Proxyをどうにかする必要がある場合
VisualStudioCodeには拡張機能等のインストールでProxyを通す必要がある場合、プロンプトを出して聞いてくれる場合や、設定ファイルに記載して通す場合もありますが、それだけだとD言語用の拡張機能で要求してくるdubがproxyを通れないため、環境変数 `http_proxy` を[設定する必要があります](https://code.dlang.org/docs/commandline)。
[環境変数の設定](https://www.google.co.jp/search?lr=lang_ja&q=%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0+%E8%A8%AD%E5%AE%9A%E6%96%B9%E6%B3%95)を行って、 `http_proxy` を設定するか、下記のように起動スクリプトに追加しましょう。
※今回は下記のような起動スクリプト(バッチファイル)を使用しました。

```bat:vscode.bat
@PATH=C:\app\dmd\windows\bin;%PATH%
@set http_proxy=http://username:password@host.example.jp:port
@start C:\app\VisualStudioCode\Code.exe
```

起動したらプロジェクトのフォルダをD&Dするなりして、プロジェクトのフォルダを開きます。

# VisualStudioCodeの拡張機能のインストール
基本的には[D Language utility extension pack](https://marketplace.visualstudio.com/items?itemName=webfreak.dlang-bundle)を入れればいいです。
が、現在依存関係先の拡張機能がうまくインストールされないようなので、その辺は手動でインストールしてやる必要があります。依存関係タブで確認しましょう。
![vscode-dlang-ext.png](https://qiita-image-store.s3.amazonaws.com/0/11147/f859e01b-5e93-c18c-7f49-f0f296110ba4.png)

あとはうまく動くか確認するだけ……と言いたいところですが、往々にしてうまくいかないことがあります。主に拡張機能の作者がテストできていない環境で問題が起こることがあります。例えばWindowsの32bit環境の事とか多分考えてなくて、64bitのバイナリをダウンロードして使おうとしたりすることがありました。その場合は自分でコンパイルします。
これら拡張機能が依存しているバイナリは、たいていdubでビルドできるので、そこまで難しくありません。
(ただし、コンパイラのバージョンとかでNGが出ることは割とありました。)
code-dだけ、コンパイラに[LDC](https://github.com/ldc-developers/ldc#installation)を要求してくるのでそのあたりが注意点でしょうか。

# VisualStudioCodeの環境設定
## settings.jsonの設定
dmdやdub、D-Scannerなどの実行ファイルへのパスを設定します。あらかじめ実行ファイルがあって、パスを通しているのであれば、改めて設定する必要はありません。また、拡張機能が自動的にダウンロードして勝手に設定してくれるので、それに任せてもいいです。(もろもろの理由でそれができないときは設定します)

## task.json/launch.jsonの設定
ビルド、デバッグのために必要です。プロジェクトの.vscodeフォルダに配置します。
ところどころdub.jsonの内容に依存しますが、だいたい以下のような感じにするとうまくいきます。
ここではdub.jsonでtargetNameに`test.exe`を、release用の設定名を configuration.nameで`gui`と指定しています。んで、Windowsで64bitバイナリを作る前提の構成になっています。

<details><summary>.vscode/task.jsonの例</summary><div>

```json:.vscode/task.json
{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "DebugBuild",
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "command": "dub build -a=x86_64 -b=debug",
            "type": "shell",
            "problemMatcher": {
                "owner": "d",
                "fileLocation": [
                    "relative",
                    "${workspaceRoot}"
                ],
                "pattern": {
                    "regexp": "^(.*)\\((\\d+),(\\d+)\\):\\s+(Warning|Error|Deprecated):\\s+(.*)$",
                    "file": 1,
                    "line": 2,
                    "column": 3,
                    "severity": 4,
                    "message": 5
                }
            }
        },
        {
            "label": "ReleaseBuild",
            "group": "build",
            "command": "dub build -c=gui -a=x86_64 -b=release -f",
            "type": "shell",
            "problemMatcher": {
                "owner": "d",
                "fileLocation": [
                    "relative",
                    "${workspaceRoot}"
                ],
                "pattern": {
                    "regexp": "^(.*)\\((\\d+),(\\d+)\\):\\s+(Warning|Error|Deprecated):\\s+(.*)$",
                    "file": 1,
                    "line": 2,
                    "column": 3,
                    "severity": 4,
                    "message": 5
                }
            }
        },
        {
            "label": "Clean",
            "group": "build",
            "command": "dub clean",
            "type": "shell"
        }
    ]
}
```
</div></details>

<details><summary>.vscode/launch.jsonの例</summary><div>

```json:.vscode/launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Debug",
            "type": "cppvsdbg",
            "request": "launch",
            "preLaunchTask": "DebugBuild",
            "program": "${workspaceRoot}/test.exe",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceRoot}",
            "environment": [],
            "externalConsole": false
        }
    ]
}
```
</div></details>


# ビルドの仕方
task.jsonをきちんと設定していれば、「タスク＞タスクの実行」からビルドできます。
拡張機能code-dがインストールされていれば、左下のBuild Projectアイコンからでもビルド実行できます。
ただ、dubの設定に慣れていない人に渡す前提の今回は、ビルド設定もろもろうまいこと設定してあげる必要があったので、task.jsonを作ってあげて、それでビルドするようにしました。

以下のような感じタスクを選択し、ビルドすることができるようになります。

![vscode-dlang-project.png](https://qiita-image-store.s3.amazonaws.com/0/11147/3bae9abc-1be8-7f17-aeb4-b450b7f06943.png)


# デバッグの仕方
launch.jsonをきちんと設定してあげれば、「デバッグ＞デバッグの開始」からデバッグ(ビルド→起動→デバッガへのアタッチの一連の処理)できます。
拡張機能code-dがインストールされていれば、左下のDebug Projectアイコンからでもデバッグできそうな気がしましたが、うまく動いてくれませんでした。

# その他
## 重い場合 2017/12/26追記
dubプロジェクトの設定で、複数のライブラリに依存していて、テンプレートを大量に使用している場合などでは、ファイルの保存のたびに複数のdmdが動き始めて、大量のメモリ消費とともにCPU負荷率を上昇させる、ということがあります。
これは、ファイル保存のたびにlint(コンパイルエラーが起こる個所を突き止める動作)がdubのbuildにより走るためです。
この場合はconfigurationを追加し、"targetType"が"library"のプロジェクト設定にするといいでしょう。こうすることで依存ライブラリのコンパイルやリンクが省略されるため、一回のlintにかかる時間・メモリ消費量・CPU負荷率が大きく削減される場合があります。

configurationは以下のような感じで定義していきます。

```json:dub.json
{
	"name": "ipc_tcp_test",
	"authors": [
		"SHOO"
	],
	"description": "AHP application.",
	"copyright": "Copyright © 2017, SHOO",
	"license": "public domain",
	"targetType": "executable",
	"dependencies": {
		"vibe-d": "~>0.7.30",
		"msgpack-d": "~>1.0.0-beta.6"
	},
	"configurations": [
		{
			"name": "test",
			"targetName": "test",
			"targetType": "library",
			"versions": ["test", "server", "client"],
			"dflags": ["-main"]
		},
		{
			"name": "server",
			"versions": ["server"],
			"targetName": "ipc_tcp_test-server"
		},
		{
			"name": "client",
			"versions": ["client"],
			"targetName": "ipc_tcp_test-client"
		}
	]
}

```

追加したら設定も変更します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/11147/df74f6ce-3dd7-a6f4-7add-07227117201f.png)


# まとめ
以下に要点をまとめます。

- インストール先に注意。深いパスにしない、VisualStudioとかWinSDKの場所に注意して、sc.iniの中身チェック。
- パスとproxyを通すために起動用のバッチとか書く。
- task.json/launch.jsonを書く。