VSCodeを用いたCMakeなC/C++開発



1. 対象

  • VSCode で C/C++開発をしたい方
  • CMake を用いた C/C++の開発を行っている方
  • Bash or Z shell 等をある程度使える方

2. できること

  • 高速な補完 (ファイルも正しく include される)
  • リンターによる静的解析
  • 保存時の整形
  • VSCode からビルド&デバッグ
  • VSCode からブレークポイントを挿入

3. 利用ソフト

  • OS

    • Ubuntu 20.04

      僕は普段から Linux を使っているので上記の OS を想定して解説します。
      その他の OS でも同様な環境が作れるので適宜読み替えてください(Windows なら WSL の利用になると思われます)
      Arch Linux でも動作を確認できています。

  • コンパイラ

    • Clang
  • エディタ

    • VSCode
      • 拡張機能
        • clangd
        • CodeLLDB
        • CMake Tools
  • 補完(Language Server)

    • clangd
    • (もしくは ccls )
  • フォーマッタ

    • ClangFormat
  • リンター

    • Clang-Tidy
  • ビルド

    • CMake + make
  • デバッガ

    • LLDB

補完について

エディタA
エディタB
言語XのLanguage Server
言語YのLanguage Server

LSP(Language Server Protocol)を用いて補完を行います
LSP を用いることで様々なエディタから補完を行うことができます。

(参考  language server protocol について (前編))

また、C++用の Language Server として clangdccls がありますが、それぞれ一長一短があります。
個人的な感想ですが

  • clangd

    • quick fix や clang tidy などの機能が豊富
  • ccls

    • 大きなプロジェクトでも重くなりにくい

この記事では clangd の利用を前提に話を進めていきます。

3.インストール

apt で入れるもの

sudo apt install  build-essential clang clangd clang-format clang-tidy cmake lldb git

VSCode

こちらから deb ファイルをダウンロード

sudo apt install /path/to/ダウンロードした.deb

PPA を追加して apt しても良いです.

4. VSCode の準備 

拡張をインストール

VSCode の 左側にある Extentions のアイコンをクリックし、上記を検索してインストールしてください。

VSCode の設定 

以下のショートカットでコマンドパレット開いてください

Windows or Linux Mac
Ctrl + Shift + P or F1 Command + Shift + P or F1

settingと打つと Preferences:Open Settings(JSON)と出てくるのでクリックします

JSON を直接編集します。

MS の C++拡張の補完を無効化 

MS の C++拡張を入れている場合は補完を無効化して下さい。

  "C_Cpp.autocomplete": "Disabled",
  "C_Cpp.errorSquiggles": "Disabled",
  "C_Cpp.intelliSenseEngine": "Disabled",
  "C_Cpp.formatting": "Disabled"

を追記

clangd 拡張の設定

clangd を起動する際の引数を設定します。
僕の設定を紹介しますが、man clangd 等で引数を調べ、お好みで設定してください。

    "clangd.arguments": [
        "--header-insertion=never", // 自動でヘッダーを挿入しない
        "--clang-tidy"// clang-tidyによるリントを有効にする。
    ]
CMake Tools 拡張の設定

続いて、CMake Tools 拡張の設定を行います。

    "cmake.generator": "Unix Makefiles", // GNU Makeを利用(Ninja等を使ってもいいがリビルドの挙動がイマイチな気がする)
    "cmake.exportCompileCommandsFile": true, // (clangd等で必要なcompile_commands.jsonを出力する)
    "cmake.copyCompileCommands": "${workspaceFolder}/compile_commands.json", // (生成されたcompile_commands.jsonを作業ディレクトリにコピーする)

上のように設定して下さい。ここで大事なのは、下の2つの設定です。clangd や Clang-Tidy はcompile_commands.json という JSON ファイルに記述されたコンパイルコマンドから、補完や静的解析を行います。しかし、このcompile_commands.json をいちいち手で書くのは大変です。幸いにも CMake にはこのcompile_commands.jsonの自動生成機能があるので、上の設定でそれを有効化することができます。 VSCode の拡張を用いずに直接 CMake のコマンドを用いる場合はCMAKE_EXPORT_COMPILE_COMMANDSという変数をONにすることで、生成することができます。make を使っている場合は bearというツールを使うことでcompile_commands.jsonを生成できます。

自動フォーマット

ファイルの保存時にフォーマットされるように設定します。

    "editor.formatOnSave": true

4.CMake プロジェクトの Configure と Generate

まず Git 等で CMake プロジェクトのクローンします。
今回は spdlog リポジトリを用いて手順を説明します。

cd 作業ディレクトリ
git clone https://github.com/gabime/spdlog.git

この作業でできた、作業ディレクトリ/spdlog/ を VSCode で開いて下さい。

続いて、CMake Tools 拡張を用いて、補完のための compile_commands.jsonの生成と CMake プロジェクトの Configure と Generate を行います。(ようはビルドします)

参考 Configure とは? 勝手に作る CMake 入門 その 1 基本的な使い方 Configure と Generate

先ほどと同様にしてコマンドパレットを開き、cmake:configure と入力しでてきた CMake:Configure をクリックして下さい。(出てこないときは拡張機能がインストールを見直して下さい)
初回だと利用するコンパイラを聞かれるので Clang を選んで下さい(バージョンは任意)
すると CMake の Configure が実行され、buildディレクトリにビルド用の Makefile が生成され、補完のためのcompile_commands.json も生成されます。

この状態になれば、clangd によって正しく補完が行われるようになります。試しにsrc ディレクトリ内のファイルを開いて補完が正しく行われていることを確認してみて下さい。

続いて CMake Generate(ビルド)を行います。下図の赤線の部分にある Build ボタンを押すとビルドが開始されます。

これで、ビルドが完了しました。

5.実行とデバッグ

VSCode から実行とデバッグを行います。
VSCode では実行とデバッグのために .vscode/launch.json というファイルを作成します。
Terminal -> New Terminal でターミナルを開いて下さい。(日本語 ver を使っている人は日本語になっています)

mkdir .vscode
touch .vscode/launch.json

launch.json が作成できるので、それを VSCode で開きます。
そして次のように入力し、保存します。

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "lldb",
      "request": "launch",
      "name": "Debug",
      "program": "${command:cmake.launchTargetPath}",
      "args": [],
      "cwd": "${workspaceFolder}"
    }
  ]
}

次に、 cmake.launchTargetPath を指定します
下図の赤線内のマークを押すとプログラムが走ります。今回ビルドされた実行可能なプログラムは exampleのみなので example が実行されます。
これで cmake.launchTargetPathexampleというプログラムを指すようになります。 実行可能なプログラムが複数ある場合は最後に実行したものが cmake.launchTargetPath に設定されます。(実行をするプログラムを選択できるようになっています。)
また cmake.launchTargetPath で実行プログラムを指定することにより、ファイルに変更があった場合にリビルドしてから実行されるようになります。
これにより、明示的なビルドの操作がなくても変更と実行を行き来することができるようになります。

さらに、LLDB でデバッグを行います。
下図の数字の順にクリックすると LLDB 上でプログラムが実行されます。

次にブレークポイントを入れてみましょう。 example/example.cpp を開き、下図のように適当にブレークポイントを入れてみて下さい。

この状態で、もう一度デバッグを起動します。(2つ前の画像のように操作)
すると、ブレークポイントでプログラムが一時停止し、変数やコールスタックを確認することができます。
マルチスレッドなプログラムの場合でも、すべてのスレットが停止するだけでなく、スレットごとのコールスタックを見ることが可能なのでとても便利です。
画面は以下のようになっています。

実行&デバッグの説明は以上です。

6.Tips

Git を利用する場合

clangd のキャッシュを無視する

clangd は .clangd or .cache というディレクトリに補完で利用するデータを格納します。
当然このようなファイルは Git の管理外にするべきなので、.gitignore してもいいのですが、他人のリポジトリだと .gitignore をいじりづらいときってありますよね。
実は個別に管理外にするファイルやディレクトリを設定することもできます。
.git/info/exclude というファイルに追記してあげればいいです

したがって

echo .cache >> .git/info/exclude
echo .clangd >> .git/info/exclude

で管理外にすることができます。

7.まとめ

VSCode でも IDE 並の開発環境を整えることができます。
もちろん最初から IDE を使えば、このようなめんどくさいことはせず快適な環境を整えられますがお金がかかったりマシンスペックが足りなかったりする方もいると思います。
そのような方にはこの開発環境はかなり良い選択肢になると思います。
また、LSP の発展により、VSCode だけでなく、Vim/Neovim や Emacs でも快適な環境を作れるようになっています。
皆さんも自分の開発環境を探求してみて下さい。

C++の開発には他にも警告や ClangTidy の設定やテストの記述、Sanitizer によるリークチェックなどさまざまな Tips があります。
このようなことについてはまた追って記事にできればと思います。