LoginSignup
10
2

More than 1 year has passed since last update.

D言語でもデバッグができる!Visual Studio CodeでD言語デバッグ環境を構築する方法

Posted at

本記事はVisual Studio Code上にD言語のデバッグ環境を整えるという趣旨の記事です。D言語に興味のない方は人生最良の行動を促すこちらの記事からご確認ください逃がさないよ?

Windowsのデバッグ環境

必要なもの

本記事はインストール方法を紹介するものではないので、各自インストールしてください。

  • Visual Studio Code
  • C/C++ ※Visual Studio CodeのC/C++言語拡張。デバッグ実行はこれを流用する。
  • dlang_cpp.natviz ※C/C++言語拡張でD言語の型を取り扱えるようにする設定ファイル。ダウンロードしてプロジェクトフォルダのどこかに置く。
  • code-d ※Visual Studio CodeのD言語拡張。プログラミング教育サービスでも映画でもないので注意。
  • ldc2 ※LLVMベースのD言語コンパイラ

ポイント

デバッグを行うには、以下について注意が必要です。

  • LDC2コンパイラを使用してビルドを行う。
  • ビルドの際64bitのバイナリにC言語形式のデバッグ情報を仕込む。
    具体的にはdubのプロジェクト設定にてdebugInfoCというbuildOptionsを設定します。
  • デバッガにはVisual Studio CodeのC/C++拡張のデバッグ機能を使う。
  • C/C++拡張のデバッグ機能にD言語設定を施す。
    具体的にはvisualizerFileに、ダウンロードしたdlang_cpp.natvisを指定します。

上記ポイントについて、以降の章で詳細な手順を示します。

ちなみに、コンパイラにldc2ではなくdmdを使用したり、dubのプロジェクト設定にてdebugInfoCの設定を行わなかったり、dlang_cpp.natvisファイルを指定しなかったりしても、ブレークポイントを張ってステップ実行したりするくらいはできます。では、上記をすると何が強くなるかというと、以下の点がサポートされるようになります。

  • 文字列がちゃんとウォッチできるようになる。ゼロ終端しなくてもちゃんと長さを解釈してくれる。
  • 配列がちゃんとウォッチできるようになる。長さも、要素ごとの展開も可能になります。
  • 連想配列もちゃんとウォッチできるようになる。

Before: image.png
After: image.png

上記画面では連想配列の変数aaの中身や、文字列の変数strの中身がキチンと表示されていることがわかります。

ビルド方法の手順

dubを使用してビルドを行います。その際、C言語形式のデバッグ情報を仕込むため、debugInfoCのオプションを設定します。

dub.json
{
    "name": "testapp",
    "targetType": "executable",
	"buildTypes": {
		"vscode-unittest": { "buildOptions": ["debugMode", "debugInfoC", "unittests"] },
		"vscode-unittest-cov": { "buildOptions": ["debugMode", "debugInfoC", "unittests", "coverage"] },
		"vscode-debug": { "buildOptions": ["debugMode", "debugInfoC"] },
		"vscode-debug-cov": { "buildOptions": ["debugMode", "debugInfoC", "coverage"] }
	}
}

上記のように、buildTypesにて各デバッグ用ビルドタイプのビルドオプションに"debugMode", "debugInfoC"を与えます。これにより、

そして、以下のようにビルドを行います。

Windows
dub build --arch=x86_64 --build=vscode-debug --compiler=ldc2

ちなみに、カバレッジ付きの単体テストが実行されるバイナリを作るには以下のようにします。

Windows
dub build --arch=x86_64 --build=vscode-unittest-cov --config=unittest --compiler=ldc2

これをVisual Studio Codeから実行するため、tasks.jsonを設定します。
以下のようになるでしょう。

tasks.json
{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "DebugBuild",
            "group": "build",
            "command": "dub build --arch=x86_64 --build=vscode-debug --compiler=ldc2",
            "type": "shell",
            "problemMatcher": "$dmd",
        },
        {
            "label": "UnittestBuild",
            "group": "build",
            "command": "dub build --arch=x86_64 --build=vscode-unittest-cov --config=unittest --compiler=ldc2",
            "type": "shell",
            "problemMatcher": "$dmd",
        }
    ]
}

あるいは、code-dが用意してくれているdubのビルドタイプを使用して以下のようにしてもよいかもしれません。

tasks.json
{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "DebugBuild",
            "group": "build",
            "type": "dub",
            "compiler": "ldc2",
            "archType": "x86_64",
            "buildType": "vscode-debug",
            "problemMatcher": "$dmd"
        },
        {
            "label": "UnittestBuild",
            "group": "build",
            "type": "dub",
            "compiler": "ldc2",
            "archType": "x86_64",
            "buildType": "vscode-unittest-cov",
            "problemMatcher": "$dmd"
        }
    ]
}

デバッグ方法の手順

デバッグ方法のlaunch.jsonの設定は以下のようになります。

launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Debug",
            "type": "cppvsdbg",
            "request": "launch",
            "preLaunchTask": "DebugBuild",
            "program": "${workspaceRoot}/testapp.exe",
            "cwd": "${workspaceRoot}",
            "visualizerFile": "${workspaceRoot}/dlang_cpp.natvis",
        },
        {
            "name": "Unittest",
            "type": "cppvsdbg",
            "request": "launch",
            "preLaunchTask": "UnittestBuild",
            "program": "${workspaceRoot}/testapp.exe",
            "cwd": "${workspaceRoot}",
            "args": ["--DRT-covopt=dstpath:cov"],
            "visualizerFile": "${workspaceRoot}/dlang_cpp.natvis",
        }
    ]
}

"visualizerFile": "${workspaceRoot}/dlang_cpp.natvis" として、D言語用の設定ファイルを指定してあげるのがポイントです。このファイルとdebugInfoCのついたバイナリを使用することで、快適にデバッグができるようになります。また、単体テストでカバレッジを出す場合は、引数に --DRT-covopt=dstpath:cov を与えることでカバレッジファイルの出力先を指定することができます。

以下が上記設定を適用したデバッグの様子です。
各設定を確認→デバッグ実行→ブレーク確認→連想配列の中身確認→単体テスト実行→ブレーク確認→カバレッジ確認を行っています。

Debug D on Windows

Linuxのデバッグ環境

必要なもの

本記事はインストール方法を紹介するものではないので、各自インストールしてください。

  • Visual Studio Code
  • lldb ※LLVMのデバッガ
  • CodeLLDB ※Visual Studio CodeのLLDB拡張。デバッグ実行はこれを使用する。
  • lldb_dlang.py ※LLDB拡張でD言語の型を取り扱えるようにする設定ファイル。ダウンロードしてプロジェクトフォルダのどこかに置く。
  • code-d ※Visual Studio CodeのD言語拡張。プログラミング教育サービスでも映画でもないので注意。
  • ldc2 ※LLVMベースのD言語コンパイラ

ポイント

デバッグを行うには、以下について注意が必要です。

  • LDC2コンパイラを使用してビルドを行う。
  • デバッガにはVisual Studio CodeでLLDBを動かすためのCodeLLDBを使う。
  • LLDBにD言語設定(lldb_dlang.py)を施す。ただし、修正が必要(2022/12/20現在)。

上記ポイントについて、以降の章で詳細な手順を示します。

ちなみに、コンパイラにldc2ではなくdmdを使用したり、lldb_dlang.pyファイルを指定しなかったりしても、ブレークポイントを張ってステップ実行したりするくらいはできます。では、上記をすると何が強くなるかというと、以下の点がサポートされるようになります。

  • 文字列がちゃんとウォッチできるようになる。ゼロ終端しなくてもちゃんと長さを解釈してくれる。
  • 配列がちゃんとウォッチできるようになる。長さも、要素ごとの展開も可能になります。
  • 連想配列もちゃんとウォッチできるようになる。

Before: image.png
After: image.png

上記画面では連想配列の変数aaの中身や、文字列の変数strの中身がキチンと表示されていることがわかります。

ビルド方法の手順

dubを使用してビルドを行います。これといって特別な設定は必要ありません。

dub.json
{
    "name": "testapp",
    "targetType": "executable"
}

そして、以下のようにビルドを行います。

Linux
dub build --arch=x86_64 --build=debug --compiler=ldc2

ちなみに、カバレッジ付きの単体テストが実行されるバイナリを作るには以下のようにします。

Linux
dub build --arch=x86_64 --build=unittest-cov --config=unittest --compiler=ldc2

これをVisual Studio Codeから実行するため、tasks.jsonを設定します。
以下のようになるでしょう。

tasks.json
{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "DebugBuild",
            "group": "build",
            "command": "dub build --arch=x86_64 --build=debug --compiler=ldc2",
            "type": "shell",
            "problemMatcher": "$dmd",
        },
        {
            "label": "UnittestBuild",
            "group": "build",
            "command": "dub build --arch=x86_64 --build=unittest-cov --config=unittest --compiler=ldc2",
            "type": "shell",
            "problemMatcher": "$dmd",
        }
    ]
}

あるいは、code-dが用意してくれているdubのビルドタイプを使用して以下のようにしてもよいかもしれません。

tasks.json
{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "DebugBuild",
            "group": "build",
            "type": "dub",
            "compiler": "ldc2",
            "archType": "x86_64",
            "buildType": "debug",
            "problemMatcher": "$dmd"
        },
        {
            "label": "UnittestBuild",
            "group": "build",
            "type": "dub",
            "compiler": "ldc2",
            "archType": "x86_64",
            "buildType": "unittest-cov",
            "problemMatcher": "$dmd"
        }
    ]
}

デバッグ方法の手順

デバッグ方法のlaunch.jsonの設定は以下のようになります。

launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Debug",
            "type": "lldb",
            "request": "launch",
            "preLaunchTask": "DebugBuild",
            "program": "${workspaceRoot}/testapp",
            "cwd": "${workspaceRoot}",
            "initCommands": ["command script import \"${workspaceRoot}/lldb_dlang.py\""]
        },
        {
            "name": "Unittest",
            "type": "lldb",
            "request": "launch",
            "preLaunchTask": "UnittestBuild",
            "program": "${workspaceRoot}/testapp",
            "cwd": "${workspaceRoot}",
            //"args": ["--DRT-covopt=dstpath:${workspaceRoot}/cov"],
            "initCommands": ["command script import \"${workspaceRoot}/lldb_dlang.py\""]
        }
    ]
}

"initCommands": ["command script import \"${workspaceRoot}/lldb_dlang.py\""] として、D言語用の設定ファイルを指定してあげるのがポイントです。このファイルを使用することで、快適にデバッグができるようになります。

しかし、lldb_dlang.pyはそのままではうまく機能しないようでした。size_tが検索できないとかのエラーが出るようです。仕方ないのでlldb_dlang.py内に出てくるsize_tをすべてulongに書き換えます。

また、単体テストでカバレッジを出す場合は、引数に --DRT-covopt=dstpath:${workspaceRoot}/cov を与えることでカバレッジファイルの出力先を指定することができ…るのですが、VSCodeにカバレッジが表示されなくなるのでコメントアウトしています。

以下が上記設定を適用したデバッグの様子です。
各設定を確認→デバッグ実行→ブレーク確認→連想配列の中身確認→単体テスト実行→ブレーク確認→カバレッジ確認を行っています。

Debug D on Linux

10
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
2