VSCode で CMake ベースの C/C++ +アプリ開発のメモ

## 背景

VSCode 標準(?)の CMake plugin だと cross compile したりビルド構成(コンパイラ変えたり)頻繁に変えるケースをうまく扱えない気がする...

しかし, VSCode のコード補完やエラー取得, デバッグ機能利用したい.

とりあえず CMake configure を外部コマンドラインで行っておき, それを使うのがよいでしょう.
`task.json`, `launch.json` 直書きで対応がよいでしょう.

## CMake configure

いつものようにして行っておきます. generator は Ninja がいいかも.  `-DCMAKE_EXPORT_COMPILE_COMMANDS=1` で `compile_commands.json` が生成されるようにしておきます.
いろいろテストして, mature になったら後述の CMakePresets.json 化がよいでしょう.

## コード補完

CMake で `compile_commands.json` 生成するようにします.
これを workspace の直下に置くか, `.vscode/c_cpp_settings.json` にパスを指定で対応します.

https://qiita.com/syoyo/items/153c232eb351e7493a9c

(VScode 上で CMake configure した場合は, 自動でこのあたり行って Intellisense 用(`C/C++ for Visual Studio Code" plugin)のを作ってくれるっぽい(したがって clangd で補完したいときはつかえない))
 
## ビルド

`tasks.json` に記述します.

```
{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "label": "build",
            "type": "process",
            "command": "make",
            "options": {
                "cwd": "${workspaceFolder}/build/"
            },
            "problemMatcher": {
                "base": "$gcc"
            },
            "group": "build"
        },
        ...
    ]
}
```

`tasks.json` は一個だけなので, 複数のビルドタスクを記述したい場合はここに複数記述します.

### エラーメッセージの補足

![Screenshot from 2022-11-04 21-46-25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36275/f2cf6c4f-5bf4-a94b-114b-30daf103426f.png)

こんなやつですね. エラーメッセージを読み取るために, `problemMatcher` で指定します.

gcc, clang だと `$gcc`, MSVC(cl.exe) だと `$msCompile` を指定します.

https://github.com/microsoft/vscode-cpptools/issues/3815

エラージャンプでファイルがうまく開けない(パスが違う)ときは, 

https://github.com/Microsoft/vscode/issues/50503

`fileLocation` を適宜設定してあげましょう.

#### clang-cl はあつかえない

clang-cl は残念ながら扱えません. :cry:

https://github.com/microsoft/vscode/issues/110946

clang-cl でクロスコンパイルのときはだめですね.
(CLion ならうまくやってくれるかも?)

## デバッグ, 実行

`launch.json` 記述で対応します.

```
{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [

        {
            "name": "(gdb) Launch",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceFolder}/build/unit-test-tinyusdz",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${fileDirname}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "setupCommands": [
                {
                    "description": "Enable pretty-printing for gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                },
                {
                    "description": "Set Disassembly Flavor to Intel",
                    "text": "-gdb-set disassembly-flavor intel",
                    "ignoreFailures": true
                }
            ]
        },
    ]
}
```

こんな感じです. 

![Screenshot from 2022-11-04 22-06-11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36275/e86b62f7-4d8b-150e-b3dc-22ad46240ef6.png)

こんな感じでブレークポイントしかけることできます

debug ビルドしていないとブレークポイントなど無視されますので注意しましょう!
(最低限関数単位で止まってもいいとおもうのですけどね)

### lldb(CodeLLDB) の場合は symlink に注意

これは CMake configure とは関係なくて一般的な lldb + vscode の問題ですが,  symlink があるとデバッグできません(`/home` あたりなどの上流で symlink している場合含む) 

https://github.com/vadimcn/vscode-lldb/issues/151

https://github.com/vadimcn/vscode-lldb/wiki/Breakpoints-are-not-getting-hit

vscode では `${workspaceFolder}` などは実パスで処理しているからソースファイルの対応が取れないからのようです.

sourceMap で元パス(symlink パス)と, 実パス(通常は `${workspaceFolder}`)の対応をしてあげれば解決します!

```
        {
            "type": "lldb",
            "request": "launch",
            "name": "Launch",
            "program": "${workspaceFolder}/build/unit-test-tinyusdz",
            "args": [],
            "sourceMap": { "/home/syoyo/work/tinyusdz": "${workspaceFolder}" },
            "cwd": "${workspaceFolder}"
        },
```

## CMakePresets.json を使う

VSCode で, CMake configure の設定を CMakePresets.json でできました(Cmake 3.20 以上必要)

現時点(2022/11)での推奨方法と思われます.

https://learn.microsoft.com/ja-jp/azure-sphere/app-development/using-cmake-functions
(`.vscode/settings.json` は単一設定しかできない)

`CMakePresets.json` は vscode 限定ではなくて, CMake の最近の機能(3.20 あたりから)なので, CMake 単体でもつかえますし, 他のツールでも使えます.

https://pleiades.io/help/clion/cmake-presets.html#load-preset

https://www.qt.io/blog/qt-creator-9-cmakepresets

クロスコンパイルとかだと JSON 編集めいどいですけどね...
(`cmake-gui` では CMakePresets.json 編集は対応していないっぽい)

`CMakePresets.json` があれば, vscode CMake plugin 側で自動で detect して configure できるようになります.
ビルド自体はいままで通り `tasks.json` に記載になります. 一応ある程度自動で以下のようにスニペット入れてくれるが, problemMatcher など適宜加筆が必要.

```
        {
            "type": "cmake",
            "label": "CMake: build",
            "command": "build",
            "targets": [
                "all"
            ],
            "preset": "${command:cmake.activeBuildPresetName}",
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "problemMatcher": [],
            "detail": "CMake template build task"
        }
```

### Run/Debug の問題

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36275/8e840326-3b2b-15cf-69bb-8007f2780699.png)

サイドバーの CMake から, 右クリックで Debug 実行とかできますが, これは `launch.json` を見ておらず(`F5` の Debug 実行と関連していない), まだデバッガも gdb only です(なんかどこかで設定できるとは思うが, ぱぱっと見つかる範囲では設定できないっぽ). さらに "C/C++ for Visual Studio Code" が入っていないと起動できません.
(`JSON with comment ~`  とかいう変なエラーがでる)

細かく環境を設定したりしてデバッグしたい場合は, `launch.json` 利用がよさそうです!

## まとめ

vscode 自体 C/C++ がメインではないこともあり, Visual Studio みたいに全部うまく完結, というわけにはいきませんでした.
ところどころ手動で対応という感じです.