個人的VSCode上でのC++開発環境

# 概要
* vscode上でc++の開発を行うにあたり、毎回環境構築で一部忘れたりするので一通り整備できるようにまとめる。
* 基本的な設定は[vscodeの公式サイト](https://code.visualstudio.com/docs)で十分だが、個人的に物足りない情報もあったのでそれらについても記載する。

## 自動環境構築(2021/10/30更新)

* Dockerコンテナ上で環境を自動構築できるようにしたものを作成しました。手っ取り早く環境を構築したい方はこちらを使用してみてください。
    * 使い方はREADMEを参照ください。

```terminal
$ git clone https://github.com/nphsgw/vscode_cpp_sample.git
```
## 環境構築の詳細

* 自動環境構築を作る前に記載した内容です。Dockerに関する記載がないなど少し古い内容です。

### 前提条件
* OSはUbuntu 18.04
* エディターはVisual Studio Code
    * 使用する拡張機能
        * C++に関する物は以下の通り
            * C/C++
            * CMake
            * Cmake tools
            * Clang-Format
        * gitでバージョン管理をする場合、詳細は触れないが以下の拡張機能があると便利
            * GitLens
            * Git History
    * .vscode以下に格納される設定ファイルに記述するは必要最低限のみとする。
* コンパイラはg++とclang++どちらも使えるようにする。
* デバッガはGDBを使用する。
    * 本当はLLDBを使いたかったが、デバッグ時にエラーが発生しそれが解決できなかったため暫定的にGDBとする。
* 言語仕様はC++17を前提とする。
* Boostライブラリを使う事を想定する。
* CMakeでクロスコンパイルできるようにする。
    * 現状はUbuntuのみのため、CMakでビルドできるところまでのまとめ
* フォーマッタはclang-formatを使用する。

# vscodeのリファレンス
* 個人的に変数はよく忘れるのでメモ
    * 変数リファレンス : https://code.visualstudio.com/docs/editor/variables-reference

# 必要なツールのインストール
## Visual Studio Codeのインストール
* [公式サイト](https://code.visualstudio.com/docs/setup/linux)に倣う。
* 拡張機能のインストールは特に迷うことはないと思うので省略。

## g++, clang++のインストール
* g++とGDBは以下のコマンドでインストール
  * `sudo apt install build-essential gdb`
* clang++は以下のコマンドでインストール
  * `sudo apt install clang`

* インストール後、バージョンを確認

```text
user@user-ubuntu:~$ g++ --version
g++ (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

user@user-ubuntu:~$ gdb --version
GNU gdb (Ubuntu 8.1.1-0ubuntu1) 8.1.1
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".

user@user-ubuntu:~$ clang --version
clang version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
```

## clang-formatのインストール
* `sudo apt install clang-format`でインストール
* インストール後、バージョンを確認

```text
user@user-ubuntu:~$ clang-format --version
clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)
```

* プロジェクトフォルダ内で以下のコマンドを実行すると設定可能パラメータが全て記載されたファイルが生成される。
  * `clang-format -dump-config -style=Google > .clang-format`
        * ここではgoogleスタイルのテンプレートを出力。
* .clang-formatがある状態で、右クリック→ドキュメントをフォーマットでルールにしたがって整形される。
    * この時複数のフォーマッタがある、といったエラーが出た場合は`xaver.clang-format`を選択
* settings.jsonに`"editor.formatOnSave":true`と記載すると保存するごとにフォーマットが適用される。

## CMakeのインストールと設定
* `sudo apt install cmake`でインストール
* インストール後、バージョンを確認

```text
user@user-ubuntu:~$ cmake --version
cmake version 3.10.2

CMake suite maintained and supported by Kitware (kitware.com/cmake).
```

* プロジェクトフォルダで以下の操作を実行
  * `ctrl + shift + p`でコマンドパレットを起動し、`CMake:クイックスタート`を選択
  * プロジェクト名を記述しENTER
  * 実行可能ファイルの作成を選択しENTER
        * プロジェクト名と同じ名前で実行ファイルが生成される
  * buildフォルダとCMakeLists.txtが生成されたことを確認。
* CMakeはデフォルトではgcc/g++でビルドするようにできているので、CMakeの`-C`オプションを使いコンパイラを変更するための設定ファイルを作成する。
  * 参考:https://qiita.com/yoyomion/items/7974bb093038c21db26d

```cmake:clang-cmake.cmake
set(CMAKE_CXX_COMPILER "/usr/bin/clang++" CACHE string "clang++ compiler" FORCE)
```

# ビルドと実行、デバッグ
## 共通設定
```text:フォルダ構成
.
├── .vscode
│     ├── c_cpp_properties.json
│     ├── launch.json
│     └── tasks.json
├── .clang-format
├── clang-cmake.cmake
├── CMakeLists.txt
├── build
└── main.cpp

```

```json:setting.json
"editor.formatOnSave": true,
"editor.fontFamily": "Yutapon coding, 'Source Han Code JP'",
"[cpp]": {
    "editor.defaultFormatter": "xaver.clang-format"
  }
```

```json:c_cpp_properties.json
{
    // 公式リファリンス
    // https://code.visualstudio.com/docs/cpp/c-cpp-properties-schema-reference
    "configurations": [
        {
            "name": "Linux g++",
            "includePath": [
                "${workspaceFolder}/**"
            ],
            "defines": [],
            "compilerPath": "/usr/bin/g++",
            "cStandard": "c17",
            "cppStandard": "c++17",
            "intelliSenseMode": "gcc-x64"
        },
        {
           "name": "Linux Clang++",
           "includePath": [
               "${workspaceFolder}/**"
           ],
           "defines": [],
           "compilerPath": "/usr/bin/clang++",
           "cStandard": "c17",
           "cppStandard": "c++17",
           "intelliSenseMode": "clang-x64"
        }
    ],
    "version": 4
}
```

```json:tasks.json
{
    "tasks": [
        {
            "type": "shell",
            "label": "C/C++: g++ build active file",
            "command": "/usr/bin/g++",
            "args": [
                "-std=gnu++17",
                "-g",
                "${file}",
                //"-lboost_system", // boostを使う場合大体必要になる。
                //"-lboost_thread", // boost::threadを使う場合は必要になる。
                "-o",
                "${fileDirname}/${fileBasenameNoExtension}"
            ],
            "options": {
                "cwd": "/usr/bin"
            },
            "problemMatcher": [
                "$gcc"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "detail": "Generated task by Debugger"
        },
        {
            "type": "shell",
            "label": "C/C++: clang++ build active file",
            "command": "/usr/bin/clang++",
            "args": [
                "-std=c++17",
                "-g",
                "${file}",
                //"-lboost_system", // boostを使う場合大体必要になる
                //"-lboost_thread", // boost::threadを使う場合
                "-o",
                "${fileDirname}/${fileBasenameNoExtension}"
            ],
            "options": {
                "cwd": "/usr/bin"
            },
            "problemMatcher": [
                "$gcc"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "detail": "Generated task by Debugger"
        }
    ],
    "version": "2.0.0"
}
```

```json:launch.json
{
    // IntelliSense を使用して利用可能な属性を学べます。
    // 既存の属性の説明をホバーして表示します。
    // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "g++ - アクティブ ファイルのビルドとデバッグ",
            "type": "cppdbg",
            "request": "launch",
            "program": "${fileDirname}/${fileBasenameNoExtension}",
            "args": [],
            "stopAtEntry": true,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "setupCommands": [
                {
                    "description": "gdb の再フォーマットを有効にする",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ],
            "preLaunchTask": "C/C++: g++ build active file",
            "miDebuggerPath": "/usr/bin/gdb"
        },
        {
            "name": "clang++ - アクティブ ファイルのビルドとデバッグ",
            "type": "cppdbg",
            "request": "launch",
            "program": "${fileDirname}/${fileBasenameNoExtension}",
            "args": [],
            "stopAtEntry": true,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "setupCommands": [
                {
                    "description": "gdb の再フォーマットを有効にする",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ],
            "preLaunchTask": "C/C++: clang++ build active file",
            "miDebuggerPath": "/usr/bin/gdb"
        }
    ]
}
```

```cpp:main.cpp
#include <iostream>
#include <string>
#include <vector>

using namespace std;

int main() {
  vector<string> msg{"Hello", "C++",     "World",
                     "from",  "VS Code", "and the C++ extension!"};
  for (const string& word : msg) {
    cout << word << " ";
  }
  cout << endl;
}
```

## g++の場合
* `ctrl + shift + b`コマンドでg++版のビルドを選択して実行
* `./main`をターミナルに打ち込み実行
* デバッガがg++向けの構成であることを確認し`F5`コマンドでデバッガが起動してmain()でstopする。

## clang++の場合
* `ctrl + shift + b`コマンドでclang++版のビルドを選択して実行
* `./main`をターミナルに打ち込み実行
* デバッガがclang++向けの構成であることを確認し`F5`コマンドでデバッガが起動してmain()でstopする。

## CMakeの場合
### g++の場合
* 以下のコマンドを実行し実行ファイルを生成

```text
cd build
cmake ..
make
```

* buildフォルダ内で`./プロジェクト名`を実行

### clangの場合
* 以下のコマンドを実行し実行ファイルを生成

```text
cd build
cmake -C ../clang-cmake.cmake ..
make
```

* buildフォルダ内で`./プロジェクト名`を実行