Windows 上の VSCode と WSL 上の GCC の連携

# はじめに
WSL は Windows 環境からシームレスに利用できることが魅力ですが、Windows 上の VSCode から [Tasks](https://code.visualstudio.com/docs/editor/tasks) を構成して WSL 上の GCC などを呼び出す方法はあまりまとまっていません。

せっかく Windows から呼び出せるなら VSCode を使って便利にコーディングしよう! ということで、この記事では VSCode から WSL 上の GCC と連携する現時点で最新の方法をまとめておきます。

なお、この記事ではソースコードやコンパイルされたプログラム等は全て Windows のファイルシステム上に保存されることを想定しています。

(Qiita 初記事なので記事全体のクオリティに関してはご容赦ください!)

# WSL と VSCode の導入
これらは検索すればいくらでも出てきますので、この記事では割愛します。

# C / C++ の IntelliSense を効かせる
Tasks を構成する前に、IntelliSense を正しく効かせないとコーディングのしようがありません。
[ms-vscode.cpptools](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) を利用している場合は、`${workspaceFolder}/.vscode/c_cpp_properties.json` に以下のように記述します。
なお、以降この記事で出てくる `$` から始まる変数は VSCode の [Variables Reference](https://code.visualstudio.com/docs/editor/variables-reference) に準拠します。

```json:c_cpp_properties.json
{
    "configurations": [
        {
            "name": "WSL",
            "intelliSenseMode": "clang-x64",
            "compilerPath": "/usr/bin/gcc",
            "includePath": [
                "${workspaceFolder}"
            ],
            "defines": [],
            "browse": {
                "path": [
                    "${workspaceFolder}"
                ],
                "limitSymbolsToIncludedHeaders": true,
                "databaseFilename": ""
            },
            "cStandard": "c11",
            "cppStandard": "c++17"
        }
    ],
    "version": 4
}
```
最新バージョンの ms-vscode.cpptool ならばこれでOKです。お好みで Path を追加してください。

# 統合ターミナルを WSL にする
現在のワークスペースフォルダ**でのみ** VSCode の統合ターミナルを WSL にするには、 `${workspaceFolder}/.vscode/settings.json` に以下のように記述します。

```json:settings.json
{
    "terminal.integrated.shell.windows": "C:\\Windows\\System32\\wsl.exe",
}
```

# Tasks を構成する
ここでは、以下のような状況を想定します。

1. ソースコードのファイル名は `${fileBasenameNoExtension}.c` or `${fileBasenameNoExtension}.cpp`
2. 出力するプログラムのファイル名は `${fileBasenameNoExtension}.out`

これを Tasks を用いて実現するには、以下のように `${workspaceFolder}/.vscode/tasks.json` を構成します。

```json:tasks.json
{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "Build (C)",
            "type": "shell",
            "command": "gcc",
            "options": {
                "shell": {
                    "executable": "C:\\Windows\\System32\\wsl.exe",
                }
            },
            "args": [
                "-Wall",
                "-Wextra",
                "-O0",
                "-g3",
                "-o",
                "`wslpath",
                "'${fileDirname}/${fileBasenameNoExtension}.out'`",
                "`wslpath",
                "'${file}'`",
                "-lm"
            ],
            "group": "build",
            "presentation": {
                "reveal": "silent"
            },
            "problemMatcher": "$gcc"
        },
        {
            "label": "Build (C++)",
            "type": "shell",
            "options": {
                "shell": {
                    "executable": "C:\\Windows\\System32\\wsl.exe",
                }
            },
            "command": "g++",
            "args": [
                "-Wall",
                "-Wextra",
                "-O0",
                "-g3",
                "-o",
                "`wslpath",
                "'${fileDirname}/${fileBasenameNoExtension}.out'`",
                "`wslpath",
                "'${file}'`",
                "-lm",
            ],
            "group": "build",
            "presentation": {
                "reveal": "silent"
            },
            "problemMatcher": "$gcc"
        }
    ]
}
```

`gcc` / `g++` のビルドオプションはお好みで変更してください。

ポイントは、`wslpath` を用いて WSL パスと Windows パスを変換してあげることと、`"options"` の `"shell"` を用いて明示的に WSL を使用するように指定してあげることです。

# (おまけ) WSL から見える Windows FS のパーミッション
WSL のデフォルトでは、`/mnt/` 以下にある Windows FS のパーミッションは 777 になっています。これには色々な問題がありますが、この記事と関係するところでは Tab 補完が全く機能しないという問題があります。

デフォルトで Windows FS のパーミッションをディレクトリは 755, ファイルは 644 などとするには、`/etc/fstab` **ではなく** `/etc/wsl.conf` に以下のように記述します。

```conf:wsl.conf
[automount]
enabled = true
root = /mnt/
options = "metadata,fmask=0133,dmask=0022"
```

# 参考文献
- [Tasks in Visual Studio Code](https://code.visualstudio.com/docs/editor/tasks)
- [tasks.json Schema](https://code.visualstudio.com/docs/editor/tasks-appendix)
- [Variables Reference](https://code.visualstudio.com/docs/editor/variables-reference)
- [vscode-cpptools & WSL Integration](https://github.com/Microsoft/vscode-cpptools/blob/master/Documentation/LanguageServer/Windows%20Subsystem%20for%20Linux.md)
- [Automatically Configuring WSL](https://blogs.msdn.microsoft.com/commandline/2018/02/07/automatically-configuring-wsl/)