colcon-cmakeの修正によるLSP対応の改善
ROS2 Advent Calendar 20日目の記事を担当します。 今回はEmacsの設定を見直して以来、とても便利に使っているLanguage Server ProtocolをROS/ROS2で、より便利に使う方法を実装したので、ご紹介します。
Language Server Protocolとは
Language Server Protocol (LSP)とはMicrosoftがVisual Studio Code用に開発していた、ソースコード解析とそれによる自動補完を行うためのサーバプロトコルです。
https://microsoft.github.io/language-server-protocol/
このLSPは現在では仕様が公開されたことで、Visual Studio Codeだけでなく、Emacs, Vimなど様々なエディタに対応したクライアントプログラムが存在しています。 そのため、Visual Studio Codeを使っていなくてもLSPのソースコード解析や自動補完による恩恵を受けることができます。
僕もLSP自体は前々から知ってはいたのですが、プログラミングするときには大概、統合開発環境のJetBrains製品を使っていて、ソースコード解析や自動補完機能が内蔵されていたので、それをそのまま使うことに慣れきっていました。 ですが、先日ひょんなことからEmacsの設定を一から見直す機会があり、lsp-modeにも対応させた結果、驚くほど気持ちよくプログラミングができることがわかりました。
clangdとpython-language-serverを組み合わせたlsp-modeは十分に幸せであることがわかったので、長らく続けたCLionのサブスクリプションを解約した。CLionでもエセEmacsキーバインドを使っていたので、むしろ正常に戻った。
— youtalk #ROS2ではじめよう (@youtalk) December 6, 2019
開発環境を見直しただけで、開発が1.5倍以上早くなった気がするし、3倍以上楽しくなった気がするし、年末の棚卸しは大事。
— youtalk #ROS2ではじめよう (@youtalk) December 10, 2019
- C++の場合には
clangd - Pythonの場合には
python-language-server
をインストールして、Emacsのlsp-modeに関連する設定項目を記述すると、ソースコード解析や自動補完が有効化されます。
colconのLSP対応の現状
ROS/ROS2の新しいユニバーサルビルドツールであるcolconも現状でもLSPにある程度以上対応しています。Pythonの場合には適切にvenv/virtualenvが設定されていれば、それに従ってpython-language-serverが起動するため、パッケージをまたぐようなソースコード解析や自動補完も卒なくこなしてくれます。
それに対して、C++の場合にはcmakeに対して、以下の様なオプションを渡して、clangdがソースコードのビルド手順を理解できるcompile_commands.jsonを生成する必要があります。
1
$ colcon build --cmake-args -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
これによって、build以下にCMakeプロジェクトのパッケージ名ごとにcompile_commands.jsonが自動生成されます。パッケージごとである理由は、colconがcatkin_toolsやcatkin_make_isolatedと同様に、パッケージごとに隔離した場所でビルドを行うようになっているためです。
これを読み込めば、src以下に配置したパッケージ間をまたがないようなソースコード解析や自動補完は有効化されます。
colcon-cmakeへのオプション追加
しかし、パッケージ開発をしている際に、毎回パッケージをまたいだらcompile_commands.jsonを読み込み直すようなことをしていたら面倒です。 そこで、パッケージ分だけあるcompile_commands.jsonを自動的に一つに統合するcolcon-cmake拡張をパパッと作れる範囲で作ってみました。
colcon build時に以下のようなオプションを追加してください。するとbuild直下に全パッケージのcompile_commands.jsonが連結されたcompile_commands.jsonが自動生成されます。
1
2
$ colcon build --cmake-concat-compile-commands --cmake-args -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
$ less build/compile_commands.json
プルリクエストにも書きましたが、何度もJSONファイルをパースしたり書き出したりしていて、非効率であることはわかっているのですが、個人的には非常に便利に使えるようになったので、結構満足しています。
colconはROS2だけでなくROSのパッケージもビルドすることができます。ですので、同じコマンドでROSの複数パッケージもソースコード解析や自動補完できます。ROSユーザはビルドツールだけでもcatkin_toolsからcolconに変更すると、その恩恵を受けられて良いのではないでしょうか。
プログラミングしながら気づいたのですが、これはcolcon-cmakeパッケージへの修正ではなく、新しいcolcon拡張を作って、colcon build後に呼ばれるように作ることが正解だと思われます。ただし、それにはcolconのプラグインの仕組みなどをきちんと理解する必要があり、1, 2時間ではできそうになかったので、今日は諦めました。 プルリクエストやイシューに誰かの反応があれば、また挑戦してみようと思います。
ブログを書いた後に別の方が、別の方法で同じ様なことを行っていることに気づきました。
https://deankh.hatenablog.com/entry/2019/10/15/231024
一つに連結するのではなく、build/*/compile_commands.jsonをsrc/*/以下にシンボリックリンクする方法だそうです。 とても手軽で良い方法なのですが、ソースとビルドのディレクトリをまたぐのは、少しだけ無作法な気もしました。 何が正解なのか、まだLSP歴が短いのでわかっていません。識者の方々にお聞きしたいです。