clang-formatの導入手順と使い方
はじめに
これは何か / 何がいいのか
clang-formatは、主にC++を対象としたソースコード整形ツール(code formatter)である。
ソースコード整形ツールは、ソースコードのフォーマット: コーディングスタイルのうちの見た目に関するものを、一定のルールに従って整形するツールである。ソースコード整形ツールを使うことで、例えばインデントの行い方やカッコの付け方などを手間をかけずに統一できる。チームで開発する際などに、全ソースコードのフォーマットをツールに任せて統一できると、フォーマットに対する好みの差によるソースコードの差分が発生しないため開発効率がよい。
C++用ソースコード整形ツールとして、2022年9月現在で名前がよく知られているのはclang-formatぐらいの様子。
clang-formatでは、整形の行い方をルールファイルで指定する。用意されているスタイル(Google C++ Style Guideなど)を指定するだけでもよいし、細かくカスタマイズしてもよい。
どうやって使うのか
下記のような使い方がある。
- エディタ上で編集中に整形する
(この記事では、VSCodeのみを扱う) - 所定のタイミングで整形またはチェックを行う
(例えば、未整形のソースコードのcommitやマージを禁止するなどの運用が考えられる)
導入手順
コマンドラインで使う場合
コマンドラインでclang-formatを使う場合には、名前のとおりのclang-format
コマンドをインストールする。
clang-formatコマンドのインストール
最近のUbuntuやDebianでは、clang-formatが標準パッケージとして提供されているので、それをインストールすればよい。手順は下記のとおり。
sudo apt install clang-format
clang-formatのバージョンを指定してインストールしたいときは、clang-format-12
などと指定する。
動作確認
シンプルなルールファイルとソースコードを使って動作を確認する。
ルールは、.clang-format
というファイルに書く。ここでは下記のものを使う。
BasedOnStyle: Google
下記のようなテスト用のソースコードを作成する。整形が行われることを確認するために、ここでは<<
演算子の前後の空白を意図的に削っている。
#include <iostream>
int main(void) {
std::cout<<"hello, world"<<std::endl;
return 0;
}
.clang-format
とhello.cpp
をカレントディレクトリに置いたら、下記を実行する。
$ clang-format hello.cpp
#include <iostream>
int main(void) {
std::cout << "hello, world" << std::endl;
return 0;
}
整形後のソースコードが標準出力に出力されて、<<
演算子の前後に空白が挿入されていれば、clang-format
コマンドが正しく機能している。
VSCodeで使う場合
Visual Studio Code上でclang-formatを使う手段はいくつかある。ここでは下記の2通りを扱う。
- C/C++拡張を使う方法 (広く使われている)
- clangd拡張を使う方法 (LLVMが公式にリリースしている / 自動整形に若干の制限がある)
なお、Clang-Format拡張もあるが、下記のようにおそらく古いものなので、理由がなければ使わないほうがよいようだ。
- Extensionとしての最終更新は2019/1/22
- clangd拡張で置き換えられた、ということなんだろうか。一次情報は特定できず
C/C++拡張による方法
広く使われているC/C++拡張からclang-formatを使う方法。
C/C++拡張にバンドルされたclang-format
コマンドか、あるいは別途インストールしたclang-format
コマンドのいずれかを使える。
C/C++拡張のインストール
VSCode上で、C/C++拡張をインストールする。
設定は、デフォルトのままで動作する様子。
必要に応じて、C_Cpp.Clang_format_path
を指定する。
任意: clang-formatコマンドのインストール
特定のバージョンのclang-formatを使いたい場合などは、コマンドラインで使う場合と同様に、clang-format
コマンドをインストールする。
clangd拡張による方法
LLVMが公式にリリースしているclangd拡張を使う方法。clang-formatは、clangd拡張の一機能として使用できる。
clangd拡張を使うためには、clangdサーバを別途インストールする必要がある。
clangdサーバのインストール
最近のUbuntuやDebianでは、clangdが標準パッケージとして提供されている。インストール手順は下記のとおり。
sudo apt install clangd
clangdのバージョンを指定してインストールしたいときは、clangd-12
などと指定する。
なお、「サーバ」とあるが、プロセスが常時動作するわけではない。VSCode上で該当する機能を使っているときに、clangd.main
というプロセスが動作するようだ。
clangd拡張のインストール
VSCode上で、clangd拡張をインストールする。
通常は、何も設定変更を行わなくてもそのまま使用できる様子。
必要に応じて、clangd.path
を指定する。
動作確認
コマンドラインツールの場合と同様に、シンプルなルールファイルとソースコードを使って動作を確認する。
下記の2つのファイルをどこかのディレクトリ内に置く。
BasedOnStyle: Google
#include <iostream>
int main(void) {
std::cout<<"hello, world"<<std::endl;
return 0;
}
VSCode上でhello.cpp
を開き、右クリックを押してメニューを表示し、ドキュメントのフォーマット
(Format Document
)を選択して実行する。<<
演算子の前後に空白が挿入されれば、正しく機能している。
なお、Format Document
の実行は、下記の手順でも行える。
- コマンドパレットで
Format Document
と入力して実行 - キーボードショートカットを使って実行
- Linuxなら
Ctrl-Shift-I
、WindowsならShift-Alt-F
(手元で確認済み) - macOSなら
Shift-Option-F
らしい (未確認)
- Linuxなら
使い方
ルールファイルの設置
clang-format
やclangd
は、ルールファイル.clang-format
を下記の順序で探す。
- カレントディレクトリにあればそれを使う
- ひとつ上のディレクトリにあればそれを使う
- 以降ルートディレクトリに至るまで同様に探し、最初に見つかったものを使う
通常は、プロジェクトのルートディレクトリに1つ.clang-format
を置いておけばよい。
ルールのカスタマイズ
ルールファイルはYAML形式で記述する。書き方は下記で詳しく説明されている。
おおまかには、下記の順序でルールを決めるとやりやすいと思われる。
調整の際には、基本スタイルの設定をダンプして読むと、設定項目とその書き方の参考になる。例えばGoogleスタイルをダンプする手順は下記のとおり。
$ clang-format --style=Google --dump-config > .clang-format
$ cat .clang-format
---
Language: Cpp
# BasedOnStyle: Google
AccessModifierOffset: -1
AlignAfterOpenBracket: Align
AlignConsecutiveMacros: false
...
基本スタイルに調整を加えた設定の一例は下記のとおり。
# Base style is Google
BasedOnStyle: Google
# Force pointers to the type for C++
DerivePointerAlignment: false
PointerAlignment: Left
# No column limit
ColumnLimit: 0
-
DerivePointerAlignment: false
+PointerAlignment: Left
- ポインタや参照を型のように扱う
-
int *a;
ではなくint* a;
になる
-
ColumnLimit: 0
- 1行の文字数の上限を無制限にする
- 横幅を広くしてエディタを使う場合には向いている
- Webブラウザ上でside-by-side表示を使ってコードレビューをする場合などには向いていない (GitHubなど)
コマンドラインでの使い方
1つまたは複数のファイルにまとめて上書きで適用するなら、下記のように-i
オプションを使用する。
clang-format -i file1.hpp dir1/file2.cpp
その他の細かい使い方は、オンラインのヘルプまたはclang-format --help
で表示されるヘルプを参照のこと。
VSCodeでの使い方
手動で整形する
整形対象のファイルを開いた状態で、下記のいずれかを実行する。
- 右クリックを押してメニューを表示し、
ドキュメントのフォーマット
(Format Document
)を選択して実行 - コマンドパレットで
Format Document
と入力して実行 - キーボードショートカットを使って実行
- Linuxなら
Ctrl-Shift-I
、WindowsならShift-Alt-F
(手元で確認済み) - macOSなら
Option-Shift-F
らしい (未確認)
- Linuxなら
自動で整形する
ファイルを保存したときに自動で整形させるなら、設定のeditor.formatOnSave
をtrue
にする。下記のいずれかの手順で設定できる。
- メニューから選ぶ、あるいは
Ctrl+カンマ
を入力するなどして設定
(Settings
)を開き、テキスト エディター
(Text Editor
)の書式設定
(Formatting
)のFormat On Save
を有効にする -
settings.json
を編集し、"editor.formatOnSave": true
を足す
C/C++拡張であれば、下記のタイミングでも自動整形できる。(clangd拡張では機能しなかった)
- 入力時に整形 (
editor.formatOnType
をtrue
にする) - ペースト時に整形 (
editor.formatOnPaste
をtrue
にする)
その他の使い方
例えば下記のような使い方ができる。
- バージョン管理ツールの機能を使って、整形なしでのcommitを禁止する
- Gitなら、
pre-commit
フックでclang-format
をかけ、整形前後で差分があったらcommitを失敗させればよい - 参考: commit時にclang-formatで修正されるファイルの有無の確認を行うhook
- Gitなら、
- GitHubでバージョン管理をしている場合に、整形なしでのpull requestのマージを禁止する
- 手段は調べていない。関連するのは下記あたりか
整形なしでの特定の操作を禁止して人間に直させるのか、あるいは自動で整形するのかは、方針に応じて選べばよい。
動作を確認した環境
項目 | 内容 |
---|---|
OS, Distribution | Debian bullseye (11.4) for amd64 |
clang-format | 11.0.1-2 |
clangd | 11.0.1-2 |
Visual Studio Code | 1.69.1 |
VSCodeのC/C++拡張 | v1.10.8 |
VSCodeのclangd拡張 | v0.1.21 |
- 標準パッケージに
clang-format
とclangd
があることは、Ubuntu 20.04.4 LTSとUbuntu 22.04.1 LTSでも確認済み
Discussion