This is supported via VS Code on OSX or Linux platforms. It might be possible to do remote debugging on Windows in conjunction with the Linux Layer.
- Requires VS Code
- install Crystal Lang extension
- install Native Debug extension
- Requires GDB
- On OSX install using Homebrew
- Then code sign the executable: https://sourceware.org/gdb/wiki/PermissionsDarwin
- The
gdb-entitlement.xmlfile is in this folder - When creating the signing certificate follow this guide
- The
This should also work with LLDB on OSX however has issues.
By convention the project directory name is the same as your application name, if you have changed it, please update ${workspaceFolderBasename} with the name configured inside shards.yml
{
"version": "2.0.0",
"tasks": [
{
"label": "Compile",
"command": "shards build --debug ${workspaceFolderBasename}",
"type": "shell"
}
]
}{
"version": "0.2.0",
"configurations": [
{
"name": "Debug",
"type": "gdb",
"request": "launch",
"target": "./bin/${workspaceFolderBasename}",
"cwd": "${workspaceRoot}",
"preLaunchTask": "Compile"
}
]
}{
"version": "0.2.0",
"configurations": [
{
"name": "Debug",
"type": "lldb-mi",
"request": "launch",
"target": "./bin/${workspaceFolderBasename}",
"cwd": "${workspaceRoot}",
"preLaunchTask": "Compile"
}
]
}Instead of putting breakpoints using commands inside GDB or LLDB you can try to set a breakpoint using debugger keyword.
i = 0
while i < 3
i += 1
debugger # => breakpoint
endCurrently, Crystal lacks support for debugging inside of blocks. If you put a breakpoint inside a block, it will be ignored.
As a workaround, use pp to pretty print objects inside of blocks.
3.times do |i|
pp i
end
# i => 1
# i => 2
# i => 3Sometimes crystal will optimize argument data, so the debugger will show <optimized output> instead of the arguments. To avoid this behavior use the @[NoInline] attribute before your function implementation.
@[NoInline]
def foo(bar)
debugger
endTo print string objects in the debugger:
First, setup the debugger with the debugger statement:
foo = "Hello World!"
debuggerThen use print in the debugging console.
(gdb) print &foo.c
$1 = (UInt8 *) 0x10008e6c4 "Hello World!"Or add &foo.c using a new variable entry on watch section in VSCode debugger
To print array items in the debugger:
First, setup the debugger with the debugger statement:
foo = ["item 0", "item 1", "item 2"]
debuggerThen use print in the debugging console:
(gdb) print &foo.buffer[0].c
$19 = (UInt8 *) 0x10008e7f4 "item 0"Change the buffer index for each item you want to print.
For printing @foo var in this code:
class Bar
@foo = 0
def baz
debugger
end
end
Bar.newYou can use self.foo in the debugger terminal or VSCode GUI.
7. Print hidden objects
Some objects do not show at all. You can unhide them using the .to_s method and a temporary debugging variable, like this:
def bar(hello)
"#{hello} World!"
end
def foo(hello)
bar_hello_to_s = bar(hello).to_s
debugger
end
foo("Hello")This trick allows showing the bar_hello_to_s variable inside the debugger tool.

