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にも対応させた結果、驚くほど気持ちよくプログラミングができることがわかりました。

  • 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を生成する必要があります。

$ colcon build --cmake-args -DCMAKE_EXPORT_COMPILE_COMMANDS=ON

これによって、build以下にCMakeプロジェクトのパッケージ名ごとにcompile_commands.jsonが自動生成されます。パッケージごとである理由は、colconcatkin_toolscatkin_make_isolatedと同様に、パッケージごとに隔離した場所でビルドを行うようになっているためです。

これを読み込めば、src以下に配置したパッケージ間をまたがないようなソースコード解析や自動補完は有効化されます。

colcon-cmakeへのオプション追加

しかし、パッケージ開発をしている際に、毎回パッケージをまたいだらcompile_commands.jsonを読み込み直すようなことをしていたら面倒です。 そこで、パッケージ分だけあるcompile_commands.jsonを自動的に一つに統合するcolcon-cmake拡張をパパッと作れる範囲で作ってみました。

colcon build時に以下のようなオプションを追加してください。するとbuild直下に全パッケージのcompile_commands.jsonが連結されたcompile_commands.jsonが自動生成されます。

$ 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.jsonsrc/*/以下にシンボリックリンクする方法だそうです。 とても手軽で良い方法なのですが、ソースとビルドのディレクトリをまたぐのは、少しだけ無作法な気もしました。 何が正解なのか、まだLSP歴が短いのでわかっていません。識者の方々にお聞きしたいです。