VSCodeとCMake(とMinGW) でC開発環境をお手軽に構築する

# はじめに
VisualStudio Code(VSCode)とgccによるC/C++開発環境をお手軽に構築します。

[CMakeの使い方（その１）の記事](https://qiita.com/shohirose/items/45fb49c6b429e8b204ac)を読ませていただき、CMakeデビューしようと思ったのですが、そもそも通常のC開発環境がないことに気付いたので、さっと用意した時の作業メモです。
(前半はCMake関係なく、通常のC開発環境構築についてです)

## 環境
- Windows10 64-bit
- VisualStudio Code(VSCode)
- MSYS2 MinGW 64-bit

## 方針
- とにかくお手軽にやる
    - ターミナル操作と組み合わせる
    - タスクランナーを使い、全部VSCode上から操作することもできるが、面倒なのでやらない
    - (ランナー用の設定ファイルやバッチファイルを書くくらいなら、ターミナルでコマンド打った方が早くない? という考え。特に、色々なプロジェクトを作ったり消したりするときは)


# 準備
## MSYS2 MinGW64の準備
- MSYS2をインストールする (https://msys2.github.io/)
- スタートメニューに作られた`MSYS2 MinGW 64-bit` `(C:\msys64\msys2_shell.cmd -mingw64)`を開く
- 言語を英語にしておく (お好みで)
    - `~/.bashrc`に以下を追加

     ```sh
     export LC_ALL=en_US.UTF-8
     export LANG=en_US.UTF-8
     export LANGUAGE=en_US.UTF-8
     ```
- 開発環境一式をインストールする

     ```sh
     pacman -Syuu
     pacman -S base-devel
     pacman -S mingw-w64-x86_64-toolchain
     pacman -S mingw64/mingw-w64-x86_64-cmake`
     ```

## VSCodeの準備
- Extensionsから、C/C++用Extension(`ms-vscode.cpptools`)を追加する

# C/C++プロジェクトを開発する
## プロジェクト用フォルダを用意する
```txt:プロジェクト構成
project1/
    - main.cpp
```
```cpp:main.cpp
#include <stdio.h>
int main()
{
	printf("Hello\n");
}
```

↑のようなフォルダを、今回はc:\project1に作ります。
このproject1フォルダをVSCodeで開きます。

## インクルードパスを修正する
VSCodeは、デフォルトでC/C++のヘッダファイル用パスを良い感じに設定してくれます。が、今回はMinGWのgccを使うので、そっちを参照するようにします。
(_注:この作業はコンパイルには影響しません。エディタ上での「定義へジャンプ」などに影響します_)

- `#include <stdio.h>`の所に、緑の波線と電球アイコンがあったら、電球マーク上にマウスカーソルを持っていき、"Edit "includePath setting"をクリック
    - もしも出なかったら、ありえないヘッダファイルをインクルードしようとして、電球マークアイコンを出す。後でこれは消す。
        - 例えば、`#include <aaa.h>`

![image.png](https://qiita-image-store.s3.amazonaws.com/0/214268/1167d536-6a2d-343d-d8fa-e8865f2d3466.png)

開かれたc_cpp_properties.jsonのWindows用設定内の、`includePath`と`path`を以下のように編集する。
これによって、「定義へ移動」などしたときに、正しいヘッダに飛んでくれます。必要に応じて、適宜追加修正してください。

```json:c_cpp_properties.json
...略...
        {
            "name": "Win32",
            "includePath": [       ↓編集↓
                "C:/msys64/mingw64/include/c++/6.2.0",
                "C:/msys64/mingw64/x86_64-w64-mingw32/include",
                "${workspaceRoot}"
            ],
            "defines": [
                "_DEBUG",
                "UNICODE",
                "_UNICODE"
            ],
            "intelliSenseMode": "msvc-x64",
            "browse": {
                "path": [       ↓編集↓
                    "C:/msys64/mingw64/include/c++/6.2.0",
                    "C:/msys64/mingw64/x86_64-w64-mingw32/include",
                    "${workspaceRoot}"
                ],
                "limitSymbolsToIncludedHeaders": true,
                "databaseFilename": ""
            }
        }
...略...
```

### インクルードパスの調べ方
MinGW上でgccでビルドするときに、`-H`オプションを付けて、どのヘッダがインクルードされているかを表示させることで、確認できます。
` g++ main.cpp -H`

## 手動でビルド&実行
```sh:MSYS2_MinGW64ターミナル
cd /c/project1
g++ -g3 main.cpp
./a.exe
```

とりあえず、最低限のC/C++コードの実装と実行はここまでの手順でできます。

## VSCodeからデバッグする
![image.png](https://qiita-image-store.s3.amazonaws.com/0/214268/00f2452f-d8f1-45e9-b07d-75490f01468c.png)

VSCode上でF5キーを押し、`C++(GDB/LLDB)`を選びます
自動で開かれるlaunch.jsonの`"program"`と`"miDebuggerPath"`を以下のように編集します。パスは環境に応じて適宜置き換えてください。

```json:launch.json
...略...
	"configurations": [
		{
			"name": "(gdb) Launch",
			"type": "cppdbg",
			"request": "launch",
			"program": "${workspaceFolder}/a.exe",    ←編集
			"args": [],
			"stopAtEntry": false,
			"cwd": "${workspaceFolder}",
			"environment": [],
			"externalConsole": true,
			"MIMode": "gdb",
			"miDebuggerPath": "C:/msys64/mingw64/bin/gdb.exe",    ←編集
			"setupCommands": [
				{
					"description": "Enable pretty-printing for gdb",
					"text": "-enable-pretty-printing",
					"ignoreFailures": true
				}
			]
		}
	]
...略...
```

もう一度F5キーを押すことでデバッグできます。ブレークポイントの設定やブレーク中に変数を見ることもできます。

ここまでで、C/C++のコードを書いて、手動でビルドして、VSCode上でGUIデバッグができるようになりました。

## CMakeでビルドする
自分でコマンドを書いたり、Makefileを作ってビルドしてもいいのですが、CMakeを使ってみます。
下記のように、CMakeLists.txtを用意します。

```txt
project1/
    - main.cpp
    - CMakeLists.txt
```

```cmake:CMakeLists.txt
project(Project1 CXX)

set(CMAKE_CXX_FLAGS "-std=c++11 -Wall")
set(CMAKE_CXX_FLAGS_DEBUG "-g3 -O0 -pg")
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -s")

add_executable(project1 main.cpp)
```

MinGWのターミナルから、ビルドします。注意点は`-G "MSYS Makefiles`を付ける点です。

```sh:MSYS2_MinGW64ターミナル
mkdir build && cd build
cmake .. -G "MSYS Makefiles"
make
./project1.exe
```

```sh:その他コマンド
cmake .. -G "MSYS Makefiles"
cmake .. -G "Unix Makefiles"     # これでも同じかも

cmake .. -G "MSYS Makefiles" -DCMAKE_BUILD_TYPE=Release    # リリース設定用Makefileを生成
cmake .. -G "MSYS Makefiles" -DCMAKE_BUILD_TYPE=Debug      # デバッグ設定用Makefileを生成
```

VSCodeからデバッグするには、以下のようにします

- cmakeコマンドは、`cmake .. -G "MSYS Makefiles" -DCMAKE_BUILD_TYPE=Debug`にする
- launch.jsonの`"program"`を`"program": "${workspaceFolder}/build/project1.exe",`に変更する

# Linuxの場合は?
手順的には全く同じです。
MinGW関係のインストールが不要です。また、gdbなどのパスの指定も、標準のものを使うのであれば、コマンド名(`gdb`)だけでOKです。