WSL & VSCode な環境でGDB環境構築(自分のはまった箇所)


`Visual Studio Code`から`Remote-WSL`を使って`WSL2`上の`Ubuntu`に接続した状態で`gdb`を使えるようにした際、いろいろはまったので、自分用のはまりポイントを公開しておきます。
あと、ついでに出来上がった設定ファイルも。
この状態で適当なcppファイルを開いたまま`F5`を押せば、gdbが起動します。

基本的に [Windows10にVSCodeでLinuxのC++開発環境を構築](https://qiita.com/yaju/items/bcd33d10746c74a00917) を参考にしています。

## バージョンとか
- Windows 10 (21H2)
- Ubuntu 20.04 on WSL2
- gcc 9.3.0
- gdb 9.2
- Visual Studio Code 1.63.2


## 自分がはまった箇所。

- ブレークポイントが無視されてしまう。
 - 別のビルドタスクから設定をコピーしてきた際、`-O0` と `-g` のオプションを忘れていたため。
 - ちなみに`-g`よりも詳しい情報が欲しければ`-g3`などにすると良いらしい。 

-  `int main()` の行で止まる。
 - `launch.json`で`stopAtEntry`を`true`にしていたため。
 - ところでサイトによっては`stopAtEntry`が`stopOnEntry`とも書かれている。謎。

- `cout`の出力が表示されない。
 - ただの勘違い。
 - デバッグを開始するとVSCodeのターミナルのうち、`デバッグコンソール` にいろいろ表示されてしまうので勘違いしていたが、実際は `ターミナル`のタブに出力されていた。

- `main()`関数の終了時に `'libstdc-start.c'が開けません。`というエラーが表示されてしまう。
 - main関数を抜けた後の部分のソースコードがないために表示される。無視するしかないらしい。
 - 参考サイト： https://knuth256.com/2021/02/22/hello-world/#toc4
 - でもポップアップは邪魔。

- Windowsのエクスプローラから`Codeで開く`を実行しても、自動では`Remote-WSL`になってくれない。[^2]
 - Windows版のターミナルとして`wsl.exe`を設定しておく。
 - これにより、`code .`のコマンド一つで`Remote-WSL`状態のVSCodeウィンドウを開くことができる。

- `~/.bash_profile`ではなく、`settings.json` の`env`にも`PATH`の設定が必要。
 - `settings.json`に適切な`PATH`設定を書かなかった場合、bashを立ち上げたときに警告が入り、環境変数`PATH`がうまく設定されない。
 - 一方、きちんと`PATH`を設定してbashを起動した場合、エラーは出なくなるが、`echo $PATH`を確認すると、別の値に上書きされている。[^1]
 - bashを実行するときの`PATH`と、bashの中で参照される`PATH`が異なる？

[^1]: 例えば`settings.json`で設定したはずの`~/.local/bin`が消えて、`~/.bash_rc`で設定した`/home/$USER/.local/bin`が含まれている。

[^2]: `.code_workspace`ファイルに`remoteAuthority`を設定すれば自動で`Remote-WSL`状態になるという記事もあるが、うまく行かなかった。

# 出来上がった構成

## フォルダ構成

wslで開きたいフォルダの直下に`.vscode`フォルダを作成し、その中に設定ファイルを格納する。

```
.vscode/
   c_cpp_properties.json
   launch.json
   settings.json
   tasks.json
```


## c_cpp_properties.json

```c_cpp_properties.json
{
  "configurations": [
    {
      "name": "WSL",
      "intelliSenseMode": "linux-gcc-x64",
      "compilerPath": "/bin/gcc",
      "includePath": ["${workspaceFolder}/**", "/usr/include/**"],
      "defines": [],
      "cStandard": "c11",
      "cppStandard": "c++17"
    }
  ],
  "version": 4
}
```

## tasks.json

- `group`は、サイトによっては`"build"`ではなく`{ "kind": "build", "isDefault": true}`と書かれている。
- 私の場合、デフォルトはonline-judge-tools用に設定しているため、デフォルト設定にはしていない。

```tasks.json
{
  "version": "2.0.0",
  "tasks": [
    {
      "type": "cppbuild",
      "label": "C/C++: g++ アクティブなファイルのビルド",
      "command": "/usr/bin/g++",
      "args": [
        "${file}",
        "-o",
        "${fileDirname}/${fileBasenameNoExtension}",
        "-O0",        // 必須
        "-g",         // 必須
        "-std=c++17"
      ],
      "options": {
        "cwd": "${fileDirname}"
      },
      "problemMatcher": ["$gcc"],
      "group": "build",
      "detail": "compiler= /usr/bin/g++ std=c++-17"
    },
    ...(他の設定のため中略)...
  ]
}
```

## launch.json

```launch.json
{
  // IntelliSense を使用して利用可能な属性を学べます。
  // 既存の属性の説明をホバーして表示します。
  // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
  "version": "0.2.0",
  "configurations": [
    {
      "name": "C/C++ Runner: Debug Session",
      "type": "cppdbg",
      "request": "launch",
      "args": [],
      "stopAtEntry": false,
      "log": true,
      "cwd": "${fileDirname}",
      "environment": [],
      "program": "${fileDirname}/${fileBasenameNoExtension}",
      "internalConsoleOptions": "openOnSessionStart",
      "MIMode": "gdb",
      "preLaunchTask": "C/C++: g++ アクティブなファイルのビルド",
      "miDebuggerPath": "/usr/bin/gdb",
      "externalConsole": false
    }
  ]
}
```

## settings.json

なお、`PATH`の`~/.local/bin`はonline-judge-tools用

```settings.json
{
  "terminal.integrated.defaultProfile.windows": "wsl",
  "terminal.integrated.profiles.windows": {
    "wsl":{
      "path":["C:\\Windows\\System32\\wsl.exe"]
    }
  },
  "terminal.integrated.defaultProfile.linux": "bash",
  "terminal.integrated.profiles.linux": {
    "bash": {
      "path":"/bin/bash",
      "args":["-l"],
      "env": {"PATH": "~/.local/bin:/bin:/usr/bin:/usr/local/bin" }
    }
  },
  "files.associations": {
    "iostream": "cpp",
    "ostream": "cpp"
  }
} 
```

## .bash_profile

- `.bashrc` を呼ぶのは、 VSCode上のターミナルで文字に色を付けて読みやすくするため。
- `settings.json`とは別に、改めてPATHが必要。
 - `tasks.json`からのコマンド実行時には`settings.json`に書いた`PATH`を参照するようだが、`bash`からは参照できないらしい。

``` /home/$USER/.bash_profile
if [ -f ~/.bashrc ]; then
    . ~/.bashrc
fi
export PATH="$PATH:/home/$USER/.local/bin"
```

# そのほか
競プロ用に`online-judge-tools`を導入しながら試行錯誤していた<del>ので、近いうちにそちら関連の備忘録も書きます。</del>