Emacs でも DAP でステップイン実行する

2020年5月現在、[実践Rust入門](https://gihyo.jp/book/2019/978-4-297-10559-4) という書籍でRustに入門しています。この書籍では2章でIDE導入について Visual Studio Code (以下 VS Code) による Rust 開発環境のセットアップについて詳しく書かれているのですが、自分も諸々の事情で Emacs から離れることが出来ないので、Emacs でも同等の機能が実現出来ないか試してみました。

LSP (Language Server Protocol) の設定については先駆者のみなさまのおかげで何の問題もなく終えることができたのですが、DAP (Debug Adapter Protocol) 実装である dap-mode をセットアップするに当たり、[公式の説明](https://github.com/emacs-lsp/dap-mode/)だけじゃさっぱり分からなかったので、elisp を読みながら試行錯誤の上なんとか動作させることに成功したので、ここにログを残しておきたいと思います。

なおこの記事では以下の環境を前提にしています。また LLVM 以外の処理系については試していませんが、ざっと他の処理系用のテンプレートを見た感じ同じアプローチで使うことが出来そうです。

* macOS Catalina
* GNU Emacs 26.3 (build 1, x86_64-apple-darwin18.2.0, NS appkit-1671.20 Version 10.14.3 (Build 18D109)) of 2019-09-02
* cargo 1.43.0
* lldb-1103.0.22.8
  Apple Swift version 5.2.2 (swiftlang-1103.0.32.6 clang-1103.0.32.51)

## VS Code をインストールする

dap-mode / dap-llvm では VS Code 用の機能拡張のラッパーとして実装されているため、[公式サイト](https://azure.microsoft.com/ja-jp/products/visual-studio-code/)から VS Code をインストールします。

## VS Code 上で機能拡張をインストールする

LLDB VSCode という機能拡張をインストールします。実践Rust入門で紹介されている CodeLLDB という機能拡張は dap-lldb で想定しているものとは別のアーキテクチャで実装されているのでここでは利用しません。（Github の [ISSUE](https://github.com/emacs-lsp/dap-mode/issues/6#issuecomment-548799016) を眺めると CodeLLDB での起動に成功している方もいらっしゃる模様）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9811/53c9e0f9-43fa-269a-20ab-663dab3ef78e.png)

## Emacs に dap-mode をインストールする

お使いのパッケージマネージャで dap-mode をインストール、以下のコードを init.el に書きます。

```elisp
(use-package dap-mode
  :custom
  (dap-lldb-debug-program `("/Users/motchang/.vscode/extensions/lanza.lldb-vscode-0.2.2/bin/darwin/bin/lldb-vscode"))
  :config
  (dap-mode 1)
  (dap-tooltip-mode 1)
  (require 'dap-lldb)
  (use-package dap-ui
      :ensure nil
      :config
      (dap-ui-mode 1)))
```
このとき、`dap-lldb-debug-program` は先ほどインストールした機能拡張の実行ファイルのパスを設定します。

## dap-debug する

`M-x dap-debug-edit-template` を実行すると、テンプレートの選択肢が出てくるので、LLDB用のテンプレートを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9811/d67f854a-fded-9a6b-8f4d-ed5a63d3bc68.png)

するとDAP サーバーを起動するためのテンプレートが開くので、これをの `:cwd` と `:program` をそれぞれクレートの root ディレクトリとdebugでビルドしたバイナリのパスに変更して `M-x e` などで eval します。

dap-mode の README が言うには init.el に永続化できるよ、との事ですが、プロジェクト固有のコードを init.el に起きたくないのでクレートの root ディレクトリにそのまま保存してしまいました。

```elisp
(dap-register-debug-template
  "LLDB::Run with lldb-vscode"
  (list :type "lldb"
        :cwd "/Users/motchang/src/github.com/motchang/rust-bicycle-book/rpn/"
        :request "launch"
        :program "target/debug/rpn"
        :name "LLDB::Run"))
```

テンプレートを eval したあとで `M-x dap-debug` をすると、先ほど編集したテンプレートの内容が一覧に表示されますので、これを選択するとデバッグセッションが開始になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9811/6b4fb146-4d4d-a42e-fec8-9ee555613634.png)

公式サイトの [How to](https://emacs-lsp.github.io/dap-mode/page/how-to/) にあるコードを使うとデバッグセッションが開始した際にIDEのようなウィンドウ配置にすることができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9811/2e0c0f23-18ef-15f6-e817-23938454d015.png)

## テンプレートについて

テンプレートの内容については、VS Cose が DAP サーバーを起動する際のパラメータになります。一度 VS Code でデバッグしたいプロジェクトを開き、デバッグ用の launch.json を自動生成させ、この内容を参照するとわかりやすいでしょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9811/a3da6b3d-53b4-bcf1-a105-b8c96e729568.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9811/8ee3323a-5d7f-bc12-1498-21971cac76ec.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9811/2f77fd65-3a25-1b35-fd31-bb45fb624854.png)

回りくどいですがこれが一番わかりやすいと思います。

また、機能拡張の公式サイトにも詳しい内容が書いてありますので、こちらも参考になります。
https://marketplace.visualstudio.com/items?itemName=lanza.lldb-vscode

## まとめ

VS Code 使おう

## We are hiring

株式会社グロービスの自分のチームでは Ruby on Rails, GraphQL, React/TypeScript というスタックでポコポコ新規サービスを作っています。 [一緒にDXをやっていっていただけるエンジニアを募集しています](https://recruiting.globis.co.jp/jobs/gdp_server+side_t/)。よろしくおねがいいたします。