Mac + VSCode + C++で競プロ環境構築

# 概要
掲題の通りです。なんかすごいハマったので自分用のメモを残しておきます。
競プロにもC++にも詳しくない人が書いているので、変なところがあったらご指摘いただけると幸いです。

なお、AtCoderにはブラウザ上でコードを実行できる機能があるため、こんなめんどくさいことしなくても参加は可能です。
ただ、ローカルで実行できるほうが速いしコード補完も効くしデバッグもできていいよねという感じです。
競プロ以外でも通用する内容は含まれているとは思いますが、競プロ用と割り切ってるので本格的な開発はこの内容だけではできないと思います。

# 環境
* macOS Monterey 12.4
* Apple M1

# gccのインストール
## 基礎知識
C++のコンパイラとしてgcc/g++があります。Macでは既定で（もしくはXcodeを入れれば？）コマンドとしては使えるのですが、既定で使えるのは実際にはgccではなく別物（Clang）のエイリアスになっているとのことです。
使えるならどちらでもいいとも言えるかもしれませんが、そのままだとbits/stdc++.hが使えないのでgccを入れるのがいいみたいです。

bits/stdc++.hをincludeするとC++の標準ライブラリを全て使えるようになるため、競プロではよく使われるようです。

## インストール
```
xcode-select --install
```
私の環境だと上記を実行した時にエラーになったので、以下を参考にして入れ直しています。
（最初はスキップしたが、コンパイルできなかったのでちゃんと入れ直した）
https://qiita.com/ismt7/items/83d8d0422f4407957a1a


次にgcc自体のインストールです。
```
brew install gcc
```

### シンボリックリンクの作成
インストールしただけだと元のgcc/g++コマンドを参照したままなので、それよりも優先順位の高い場所にシンボリックリンクを作成します。

私の環境だと以下のようなコマンドになりました。
```
sudo ln -s /opt/homebrew/bin/gcc-11 /usr/local/bin/gcc
sudo ln -s /opt/homebrew/bin/g++-11 /usr/local/bin/g++
```

`gcc -v` と `g++ -v` を実行して、なんかHomebrewで入れたやつっぽい出力になったらOKです。

# VSCodeのインストールと設定

エディタ、IDEはなんとなくVSCodeにしてみました。ここからはごちゃごちゃしているというか、トライアンドエラーを繰り返してこうなったので、実は不要な手順とかもあるかもしれません。

順を追って書いていきます。

## VSCodeのインストール

```
brew install --cask visual-studio-code
```

## とりあえず実行するのに必要な拡張機能のインストール、設定

デバッグ実行については後述します。とりあえずデバッグなしで実行するのには以下の拡張機能を入れます。

* C/C++
* C/C++ Clang Command Adapter
  * 参考サイトに従って入れていますが必要なのかよくわかりません
  * gccでなくClang依存のツールなのが気になる… とりあえず何か変になったら無効化してみようくらいのスタンス
* CodeRunner
  * コードの実行用ですが、後述のデバッグ実行で事足りるのでいらないかもしれません

なお、以下からはVSCodeで特定のディレクトリをプロジェクトディレクトリとして開いている前提で書いています。
ターミナルから `code .` でカレントディレクトリをプロジェクトディレクトリとしてVSCodeを開くことができます。[^1]
[^1]: これを実行するためにもしかしたら以下のような手順が必要かもしれません。私も昔やったかもしれないけど定かではありません。
https://qiita.com/naru0504/items/c2ed8869ffbf7682cf5c

### c_cpp_properties.json の設定
`.vscode/c_cpp_properties.json` を作成します。（本来コマンドで作成するようですが、私の場合はよくわからないうちに作成されていたので詳細はわかりません）

私の場合は以下のような内容になりました。

```c_cpp_properties.json
{
    "configurations": [
        {
            "name": "Mac",
            "includePath": [
                "${workspaceFolder}/**",
                "/opt/homebrew/Cellar/gcc/11.3.0_1/include"
            ],
            "defines": [],
            "macFrameworkPath": [
                "/System/Library/Frameworks",
                "/Library/Frameworks"
            ],
      
            "compilerPath": "/opt/homebrew/bin/g++-11",
            "cStandard": "c11",
            "cppStandard": "c++17",
            "intelliSenseMode": "clang-x64"
        }
    ],
    "version": 4
}
```

### settings.json の設定
settings.json はVSCode自体の設定ファイルです。そこに以下の内容を追記します。
明らかに今回の内容には関係ないものもの含まれますがとりあえずそのまま載せています

```settings.json
{
    "clang.executable": "clang++",
    "code-runner.runInTerminal": true,
    "clang.cxxflags": [ "-std=c++17"],
    "code-runner.executorMap": {
        "javascript": "node",
        "java": "cd $dir && javac $fileName && java $fileNameWithoutExt",
        "c": "cd $dir && gcc $fileName -o $fileNameWithoutExt && $dir$fileNameWithoutExt",
        "cpp": "cd $dir && g++ -O2 -std=c++17 $fileName && ./a.out",
        "objective-c": "cd $dir && gcc -framework Cocoa $fileName -o $fileNameWithoutExt && $dir$fileNameWithoutExt",
        "php": "php",
        "python": "python -u",
        "perl": "perl",
        "perl6": "perl6",
        "ruby": "ruby",
        "go": "go run",
        "lua": "lua",
        "groovy": "groovy",
        "powershell": "powershell -ExecutionPolicy ByPass -File",
        "bat": "cmd /c",
        "shellscript": "bash",
        "fsharp": "fsi",
        "csharp": "scriptcs",
        "vbscript": "cscript //Nologo",
        "typescript": "ts-node",
        "coffeescript": "coffee",
        "scala": "scala",
        "swift": "swift",
        "julia": "julia",
        "crystal": "crystal",
        "ocaml": "ocaml",
        "r": "Rscript",
        "applescript": "osascript",
        "clojure": "lein exec",
        "haxe": "haxe --cwd $dirWithoutTrailingSlash --run $fileNameWithoutExt",
        "rust": "cd $dir && rustc $fileName && $dir$fileNameWithoutExt",
        "racket": "racket",
        "ahk": "autohotkey",
        "autoit": "autoit3",
        "dart": "dart",
        "pascal": "cd $dir && fpc $fileName && $dir$fileNameWithoutExt",
        "d": "cd $dir && dmd $fileName && $dir$fileNameWithoutExt",
        "haskell": "runhaskell",
        "nim": "nim compile --verbosity:0 --hints:off --run",
        "lisp": "sbcl --script",
        "kit": "kitc --run"
    },
    "C_Cpp.codeAnalysis.clangTidy.headerFilter": ""
}
```

これで `control + option + N` で実行できるようになります。

しかし私の環境だと、これだけだとVSCode上では `#include <bits/stdc++.h>` の部分でエラーの表示になってしまいました。
仕方ないのでエラーを抑制するためのアドホックな対応を行いました。

`/usr/local/include` の下に `bits` ディレクトリを作成し、そこに `/opt/homebrew/Cellar/gcc/11.3.0_1/include/c++/11/aarch64-apple-darwin21/bits/stdc++.h` をコピーしたらエラーが消えました。

## デバッグ実行できるようにする

ここまでで満足しかけましたが、そうはいきません。デバッグ実行できなければわざわざローカルに環境構築する旨味があまりありません。

デバッグ実行のためには以下の拡張機能を入れます。

* CodeLLDB

上記がなくても可能ではあるのですが、これを使ったほうが便利そうでした。

### 基礎知識
デバッグ実行にはデバッガが必要です。C/C++でよく使われるデバッガとしてgdbやlldbがあるようです。デバッガ自体はコマンドラインツールですが、エディタやIDEと連携してGUI操作で使うことの方が多いです。
CodeLLDBはlldbとVSCodeを連携させるための拡張機能ということですね。なのでlldbのほうを使います。gdbも試そうとしたのですが挫折しました…

なお、lldb自体は付属のものを使うのでインストール不要です。

### tasks.json の作成

ビルドタスクのためのファイルを `.vscode/tasks.json` として作成します。（これも本来コマンドで作成するのですが以下略）

私の場合は以下の内容になりました。

```tasks.json
{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "Build with gcc",
            "type": "shell",
            "command": "g++",
            "args": [
                "-std=c++17",
                "-gdwarf-3",
                "test.cpp",
                "-o",
                "a.out",
                "--debug"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            }
        }
    ]
}
```

色々適当ですが、`test.cpp` に記述したソースを元にビルドするという内容になります。競プロ用ならそんなもんで十分ですね。
`-gdwarf-3` の部分ですが、これがないとvectorの中身を想定通り表示させることができませんでした。（人間にわかりやすい表示ではなく、内部構造をそのまま表示しちゃう）
lldbを直接実行してもうまく表示されなかったのでlldbの問題な気がします。

対処方法の意味はよくわかっていないのですが、これもおそらくアドホックな対応なのでしょうね。先人の記事ではこれがなくても表示できていたようなので、言語やツールのバージョンアップで変わってしまった（lldbがまだ追いついていない）とかそういう感じではないでしょうか。

### launch.json の作成
デバッグ実行の定義を `.vscode/launch.json` に記述します。このファイルも本来は以下略

私の場合は以下の内容になりました。ファイル名やタスク名はtasks.jsonと合わせる必要があります。

```launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(lldb) Launch",
            "type": "lldb",
            "request": "launch",
            "program": "${workspaceFolder}/a.out",
            "args": [],
            "cwd": "${workspaceFolder}",
            "preLaunchTask": "Build with gcc"
        }
    ]
}
```

これで、 `実行 -> デバッグの開始` でデバッグ実行できるようになります。（ショートカットキーやTouch Barでも可）

こんな感じになりました。
![スクリーンショット 2022-05-29 20.23.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321705/49dbc77e-4fd1-cb88-3495-2283a3ab1087.png)

標準入力は下のコンソールから入力できます。

# おまけ
サクッと構築するつもりだったのにほぼ一日無駄にしました…　
C++にこだわらずPythonとかでやればよかった可能性も。

# 参考サイト
* https://qiita.com/YasufumiNakama/items/6efa6975f551a1986e89
* https://qiita.com/tom_sapiens/items/c4c4b7de2201272a94db
* https://qiita.com/ShibuKazu/items/94bb4f1314d9ba323296
* https://zenn.dev/takuho/articles/cea703bde06732
* https://kunolog.com/m1_vscode/
* https://qiita.com/granddaifuku/items/c26b58b89d73b4a3de98
* https://qiita.com/hakatashi/items/f9d9abf05a002b5c4dc5