最近,Perl の開発してるときに DDP とかでダンプするのが億劫になってきたのと, 動かしつつデバッガーでブレークポイント置くみたいな体験できないかな,という気持ちが高まってきたので, そういうことができないか,というのを模索してみることにした.
前提
目下使っているエディタは VSCode である. これのデバッガー機能が使えればナイスな感じがしてくる.
環境は Docker で構築されている.Plack で動いている.Plack は正直わかってない.
ただ,調べてもあまり Perl + VSCode のリモートデバッグでやったぜみたいなものはあまり出てこない.
素直に Perl Debug
素直に Perl Debug という拡張を使ってみることにした
1. Perl Debug のインストール
2. Devel::vscode
の導入
あとは Devel::vscode
も導入しておく:
3. アプリケーション側の設定
ブートストラップ的なコードを起動する際に,PERLDB_OPTS
にリモートのどこにアクセスするのか指定しておく.今回は Docker のコンテナ内からホストなので host.docker.internal:9875
とかにしておく.
あとは Devel::vscode
をロードしておくために -d:vscode=fork=break
とかを指定しておく.これは先述した Perl Debug のページに説明がある:
PERLDB_OPTS="RemotePort=host.docker.internal:9875" carton exec -- perl -d:vscode=fork=break "path/to/bootstrap.pl" "$@"
4. launch.json
の設定
VS Code 側の launch.json
はあわせてこうしておく:
{ "version": "0.2.0", "configurations": [ { "name": "Remote Perl", "type": "perl", "port": 9875, "request": "launch", "root": "${workspaceRoot}", "program": "${workspaceRoot}/${relativeFile}", "console": "remote", "sessions": "watch", "debugLog": true, "debugRaw": true, "stopOnEntry": true } ] }
コンテナ内ではアプリケーションコードは /app/
以下に置いていて,ホスト側のワークスペースでのパスと微妙に対応しないので,シンボリックリンクをはっておく.
これで 9875 番で待機している VS Code につないでくれるはずだ.
5. おもむろにデバッグ
と,待っていたら,とりあえずスクリプトの先頭で止まってくれた:
しばらく待ってるとコールスタックが山盛り積まれはじめた:
先頭では止まることができるけど,それ以降ロードされたコードで止まれないみたいな感じになっている.なので,肝心のアプリケーション側のコードで止まれない.
デバッグコンソールを見ていると vscode: new loaded source (ロードされたソースへのパス)
とは出てきている.
Perl Debug のコードだとこの辺りだろうか.新しく読み込まれたソースファイルをローズするところがうまくいかない感じがしている:
といったところでうまく行かなすぎて頓挫した.Perl Debug 自体をデバッグして追っていけばなにか分かるかもしれないが元気が出なかった.
あとfork
しているあたりが不穏で,そこからうまく行ってなさそうな気もしている.
DBGp
もうひとつ見つけた:
これは DBGp というプロトコルを使ってデバッグできるようにしてくれるもの,ということで,DBGp というのは PHP のデバッグに使われている xdebug のプロトコルである.
xdebug はリモート側で動いている PHP から クライアントのデバッガーに対してコネクションをはってデバッグするというものになっている.
これにのっとるということで,いわば xdebug の Perl 版のアダプタみたいになっているようだ.
ただ VSCode で DBGp に対応してるデバッグ拡張が PHP Debug しかなくて,これでうまくいくのかが不安しかない:
DBGp
トライ
さっそく使ってみようということで,やることは以下:
Plack::Middleware::DBGp
追加- Plack の
builder
のところでuse
してコネクションの情報を設定しておく - PHP Debug 拡張を入れておく
launch.json
にデバッガーの設定を追加- おもむろにデバッグをはじめる
1. cpanfile
にいれる
requires 'Plack::Middleware::DBGp';
2. use
する
use Plack::Middleware::DBGp ( remote_host => 'host.docker.internal:9000', ); use Plack::Builder; # ... builder { # ... enable 'DBGp'; $app; };
4. launch.json
設定
{ "version": "0.2.0", "configurations": [ { "type": "php", "request": "launch", "name": "DBGp", "program": "${workspaceFolder}/${relativeFile}", "pathMappings": { "<rootOnRemote>/": "${workspaceFolder}/" }, "stopOnEntry": true, "port": 9000, } ] }
5. おもむろにデバッグをはじめる
ブレークポイント置いて待ってたけど
まったく始まる気配ゼロ. 大失敗.
DBGp
デバッグのデバッグ
しかたないのでコネクションが来てるかだけでも確認してみる. ということで,Wireshark で TCP 9000 番に DBGp っぽいのが来てるか確認することに.
DBGp
のプロトコルは XML を投げつけられて始まるので,XML が投げつけられてきているか確認すればよさそう.
見た感じでは,XML は投げつけられてきている.
そもそも VS Code でできるのか
当初から脳裏によぎってたように PHP Debug の拡張では難しいのではないか,という疑問がある.
ということでモジュールのページの確認がとれてる拡張のリストに名前のあった Sublime Text のプラグインで確認してみた:
コネクションは来た.けど,それ最初以降進めなくて詰んだ.
IntelliJ IDEA
この記事を参考に IntelliJ IDEA でやってみたけど, これでも最初のところでは止まるけど,それ以降ロードされたものでうまく行かなかった.
ので,なにかが決定的に欠けててうまく行ってない説が濃厚.
結論
盛大に頓挫した.まったくできない,とかではなくて,微妙にできてるのがたちが悪くて諦めきれない感じなっている.Perl 力が低くて勘所がわからないのも関係してそうな気がしている.
fork
しているあたりでうまく行ってない説がある.ふんわりとそこが境界になっている気がしている.
なので,スキをみて試行錯誤したい所存だけど,この検証だけでも結構時間がかかってしまって,非常に精神力を必要とするものになっている.
他のフレームワーク
余談として Laravel とかはフレームワーク側でがんばって,ルーティングとか SQL のトレース情報をページ上なり Chrome の拡張なりで確認できるものがあったりする:
Perl でもお手製で Socket.IO とかなんなりの手段を使って各種トレースを投げつけるようにすれば,こういうこともできたりするだろうな,と夢想したりした.