EmacsでC/C++用にclangdとclang-formatを使う
この頃のエディタはlanguage server protocol (LSP) という規格で,補完とか整形を外部ツールと通信することで実現している.Emacsでもclangd/clang-formatというLLVMが提供するツールを使えば簡単にリッチなC/C++環境が作れる.
環境
- Spacemacs [email protected]
- Ubuntu 18.04
clangd のインストール
Debian系のLinuxを使っていればaptが使える.現時点でstableなver 6.0を次のように入れた.
sudo apt-get install clang-tools-6.0 clang-format-6.0
18.04なら恐らく /etc/apt/sources.list
などに追記する必要はないと思うが,パッケージが見つからない場合は下記のページを元に設定してほしい.
デフォルトではPATHが通っていないので,以下のように .bashrc
に追記して通した.
export PATH=/usr/lib/llvm-6.0/bin:$PATH
Emacs 向けの設定
M-x package-install lsp-mode lsp-ui company-lsp clang-format
(add-hook 'c++-mode-hook 'company-mode) ; 補完用
(add-hook 'c++-mode-hook 'flycheck-mode) ; チェック用
(add-hook 'c++-mode-hook #'lsp)
- lsp-mode: 各種LSPの言語モードを実装している C/C++ の設定もここに含まれている.
- company-lsp: 補完を担うcompany-modeのLSP向け設定
- lsp-ui: ドキュメントの表示など各種アクションを実装している.デモ用のGIF動画がある https://github.com/emacs-lsp/lsp-ui
Spacemacs向けの設定
.spacemacs
の各セクションに追記する
(defun dotspacemacs/layers ()
;; ...
(setq-default
;; ...
dotspacemacs-additional-packages
'(
;; LSP用のパッケージ
lsp-mode
lsp-ui
company-lsp
clang-format
)
))
(defun dotspacemacs/user-config ()
;; ...
(add-hook 'c++-mode-hook 'company-mode) ; 補完用
(add-hook 'c++-mode-hook 'flycheck-mode) ; チェック用
(add-hook 'c++-mode-hook #'lsp)
)
ファイル単位の動作
ファイルを開くと選択肢がでてくるので Do nothing ...
を選んだ.
clang-formatのデフォルトのコマンドは M-C-\
らしい.デフォルトのC++モードではC++17から追加になった if constexpr
などでフォーマットが崩れていたのできちんと整形されて嬉しい.キーバインドの設定はREADMEを読むか,redditに投稿されていたやつを使うとよい.
flycheckがコンパイル時のWarningやErrorの箇所が色付き下線で表示する,そこにカーソルを置くとメッセージが読める.companyは標準ライブラリなどは補完してくれる.競プロとかで便利そう._大文字
から始まる内部データまで見えるのは,よくないが...うまく設定できないだろうか
プロジェクト単位の動作
以下の2つのファイルを同じディレクトリに置いた.
- Makefile
CXXFLAGS := -std=c++17 -Wall -Wextra -std=c++17 -I$(HOME)/tool/boost_1_67_0/stage/include -L$(HOME)/tool/boost_1_67_0/stage/lib -lboost_serialization
main.out: main.cpp lib.o
$(CXX) $^ -o $@ $(CXXFLAGS)
%.o: %.cpp
$(CXX) -c $< $(CXXFLAGS)
- lib.hpp
namespace lib {
int add(int x, int y);
}
- lib.cpp
namespace lib {
int add(int x, int y) {
return x + y;
}
}
- main.cpp
#include <boost/serialization/serialization.hpp>
#include "lib.hpp"
using namespace boost::serialization;
int main() {
auto x = lib::add(1, 2);
}
Import project root ...
みたいなやつを選ぶと,lsp-uiが起動して明らかに先程の1ファイルを開いたときとは違う見た目になる.そして当たり前のようにローカルの lib.hpp
内の関数が補完にでてくる.
Makefileに書いただけだが,普通に外部ライブラリのboostも補完された.
詳細な設定
- clang-format
公式ドキュメントを読んで .clang-format
をプロジェクト配下に置く.なお再帰的に親ディレクトリを見に行くっぽいので,$HOMEディレクトリによく使う設定を置くと便利.私は下記ページの一番下のVisualStudioっぽい設定が好きなので使っています.
- clangd
clangd もさすがに全てのオプション(たとえば-std=c++17とか)は見てくれなさそうだなと思った所,compiledbというツールを使えば設定ファイルのjsonを履いてくれるらしい.便利だ.
設定ファイルの仕様 https://clang.llvm.org/docs/JSONCompilationDatabase.html
今回のMakefileからcompiledbが生成したjsonは以下の通り
pip install compiledb
compiledb make
[
{
"directory": "/home/skarita/Desktop/test",
"arguments": [
"g++",
"-c",
"lib.cpp",
"-std=c++17",
"-Wall",
"-Wextra",
"-std=c++17",
"-I/home/skarita/tool/boost_1_67_0/stage/include",
"-L/home/skarita/tool/boost_1_67_0/stage/lib",
"-lboost_serialization"
],
"file": "lib.cpp"
},
{
"directory": "/home/skarita/Desktop/test",
"arguments": [
"g++",
"main.cpp",
"lib.o",
"-o",
"main.out",
"-std=c++17",
"-Wall",
"-Wextra",
"-std=c++17",
"-I/home/skarita/tool/boost_1_67_0/stage/include",
"-L/home/skarita/tool/boost_1_67_0/stage/lib",
"-lboost_serialization"
],
"file": "main.cpp"
}
]
このjsonファイル以外にもcompile_flags.txt
というファイルに1行1オプション羅列する方法もある.
-Wall
-Wextra
-std=c++17
-I....
-L....
-lboost_serialization
感想
今回は簡単なプロジェクトで使ってみたが,数十ファイルの巨大プロジェクトでもかなり軽快に動いている印象がある.外部プロセスなのでエディタに負荷が少ないのかもしれない.
Author And Source
この問題について(EmacsでC/C++用にclangdとclang-formatを使う), 我々は、より多くの情報をここで見つけました https://qiita.com/kari_tech/items/4754fac39504dccfd7be著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .