c/cpp言語 + Visual Studio CodeのIntelliSense(include path)設定をcmakeから自動生成する

# 解決したいこと
- VSCodeでc/cpp言語の開発をしているとき、外部ライブラリやヘッダファイルの場所が正しく設定されていないと、関数定義へのジャンプなどが使えない
- `.vsode/c_cpp_properties.json` の`includePath` にパス設定をすることで解決できるが、いちいち調べて設定するのが面倒くさい
- cmakeをしたらパスは分かっているはずなので、cmakeにその設定をしてもらう
- 参考: https://stackoverflow.com/questions/36122358/visual-studio-code-c-include-path/50360945#50360945

## 解決方法
- CMakeLists.txtに`set(CMAKE_EXPORT_COMPILE_COMMANDS ON)` を追加する
    - これによって、build先に`compile_commands.json` が生成される
    - 注意: なので、cmakeファイルを一通り書いたら、コードを書く前に一度cmakeコマンドを実行する必要がある
- `c_cpp_properties.json` に以下を追加し、上記設定を読み込む
    - `"compileCommands": "${workspaceFolder}/build/compile_commands.json"`

↓以下、具体例↓

## 前提
- Ubuntu, g++, gdb, cmake
- VSCode
    - ms-vscode.cpptools
- 例題
    - main関数から外部ライブラリとしてOpenCVを使う例を考える

## 構成
```txt
├── .vscode/
│   ├── c_cpp_properties.json
│   └── launch.json
├── CMakeLists.txt
├── main.cpp
└── build/
```

# コード
## main.cpp
- 以下の例だと、OpenCVを使用しているが、このままだとヘッダファイルも開けないし、cv::xxx関数の定義へのジャンプもできない
- また、include文の下に波線のエラーが出る

```c:main.cpp
#include <cstdio>
#include <opencv2/opencv.hpp>

int main(int argc, char* argv[])
{
    printf("Start\n");

    int a = 123;
    printf("a = %d\n", a);

    cv::Mat image = cv::Mat::zeros(32, 32, CV_8UC3);
    cv::imshow("image", image);
    cv::waitKey(-1);
    
    printf("Finish\n");
    return 0;
}
```

## CMakeLists.txt
- cmake内でOpenCVの設定はしているのでビルドは通る
- `set(CMAKE_EXPORT_COMPILE_COMMANDS ON)` によってその設定をjsonで出力させているのがポイント
- この設定は、topのCMakeLists.txt内で1つあればOKっぽい。例えば、子モジュールをadd_subdirectoryして、その子モジュールが他のライブラリに依存していたら、そこへの参照設定もちゃんと出力してくれた

```txt:CMakeLists.txt
cmake_minimum_required(VERSION 3.0)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

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

set(ProjectName "main")
project(${ProjectName})

add_executable(${ProjectName} main.cpp)

find_package(OpenCV REQUIRED)
target_include_directories(${ProjectName} PUBLIC ${OpenCV_INCLUDE_DIRS})
target_link_libraries(${ProjectName} ${OpenCV_LIBS})
```

## c_cpp_properties.json
- 先ほど出力した`compile_commands.json` を読み込む。必要に応じてjsonファイルのパスは変更する
- この状態で、ターミナルからcmakeを実行すると、`compile_commands.json` が生成され、インテリセンスが正しく設定される

```json:c_cpp_properties.json
{
    "configurations": [
        {
            "name": "Ubuntu",
            "includePath": [
                "${workspaceFolder}/**"
            ],
            "compileCommands": "${workspaceFolder}/build/compile_commands.json"
        }
    ],
    "version": 4
}
```

## おまけ: launch.json
- 本題とは関係ないが、gdbデバッグするための設定
- `cmake .. -DCMAKE_BUILD_TYPE=Debug` , `make` , F5

```json:launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(gdb) Launch",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceFolder}/build/main",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "miDebuggerPath": "gdb",
            "setupCommands": [
                {
                    "description": "Enable pretty-printing for gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ]
        }

    ]
}
```