Sunday, November 22, 2009

How to enable Ruby debug in RubyMine 2.0 on Windows

I recently had the chance to evaluate JetBrains' RubyMine. I was well impressed by this IDE except for the impossibility to debug Ruby code.
However I didn't gave up and, googling a bit, I found a thread inside JetBrains Developer Community that helped me to fix my installation and finally to debug Ruby code inside RubyMine.
Although the entire procedure is fully described in that thread, I think is worth summarizing the fundamental steps to fix the environment.
Let's start from a scenario where Ruby 1.9 has been installed with the one-click installer and RubyMine 2.0 has been installed too. (If you installed Ruby with the zip binary, reinstall it using the one-click installer as found here. That's because currently the ruby debugger ide only works on Windows using a RubyInstaller installation). Also verify that Ruby's root path doesn't include spaces.
  1. Download Ruby DevKit. (The links brings you to a .7z file, that you can open with 7Zip).
  2. Open the .7z file and follow the instructions in INSTALL file: basically they said to extract top-level folders (i.e. bin and devkit) to the Ruby's root folder and to modify the contents of fstab file according to your installation. In my case, my Ruby folder was: C:\programmi\ruby19, so my fstab file contents became:
    C:\Programmi\Ruby19\devkit\gcc\3.4.5\mingw32 /mingw
    C:\Programmi\Ruby19\devkit\msys\1.0.11\usr\local /usr/local
  3. Execute the command gem install ruby-debug-ide19
    (Note that's fundamental to install ruby debug ide as ruby-debug-ide19 because RubyMine looks for a gem with name ruby-debug-ide19 and not ruby-debug-ide, as you would expect). Also be patient because the command takes a while to complete.
  4. Open with a text editor the file command.rb that's part of the installed ruby-debug-ide19 gem. In my case, that file was under folder C:\Programmi\Ruby19\lib\ruby\gems\1.9.1\gems\ruby-debug-ide19-0.4.12\lib\ruby-debug
  5. Modify the beginning of procedure debug_eval (at line 120) so to enter a new statement between statements str = str.to_s and max_time = 10. The new statement to enter is:
    return "" if str == "$FILENAME"

    At the end, the procedure debug_eval should begin like this:
    def debug_eval(str, b = get_binding)
      begin str = str.to_s
      return "" if str == "$FILENAME"
      max_time = 10
      to_inspect = str.gsub(/\\n/, "\n")
  6. Save the file
That's it. Enjoy Ruby debugging with RubyMine!

9 comments:

Atlas Apollo said...

Hi,

Thank you very much for posting this. It works beautifully, and even though I still do not know how to use the debugger, it no longer crashes when I try to use it!!

I appreciate it very much,
All the best,
Mike

Hoang Nghiem said...

Thank you very much! That's works perfectly!

Wroolie said...

Success after hours of errors. Thank you very much Giorgio.

Laran Evans said...

Whew! Thanks for the tip.

How did you find out about this, devkit in particular?

BDVS said...

Sounds great, but just tried it with results:

C:\Documents and Settings\brians>ruby -v
ruby 1.9.1p243 (2009-07-16 revision 24175) [i386-mingw32]

C:\Documents and Settings\brians>gcc -v
Reading specs from C:/Ruby19/bin/../devkit/gcc/3.4.5/bin/../lib/gcc/mingw32/3.4.
5/specs
Configured with: ../gcc-3.4.5-20060117-3/configure --with-gcc --with-gnu-ld --wi
th-gnu-as --host=mingw32 --target=mingw32 --prefix=/mingw --enable-threads --dis
able-nls --enable-languages=c,c++,f77,ada,objc,java --disable-win32-registry --d
isable-shared --enable-sjlj-exceptions --enable-libgcj --disable-java-awt --with
out-x --enable-java-gc=boehm --disable-libgcj-debug --enable-interpreter --enabl
e-hash-synchronization --enable-libstdcxx-debug
Thread model: win32
gcc version 3.4.5 (mingw-vista special r3)

C:\Documents and Settings\brians>gem install ruby-debug-ide19
Building native extensions. This could take a while...
Building native extensions. This could take a while...
ERROR: Error installing ruby-debug-ide19:
ERROR: Failed to build gem native extension.

C:/Ruby19/bin/ruby.exe extconf.rb
checking for rb_method_entry_t.body in method.h... no
checking for vm_core.h... no
checking for rb_method_entry_t.body in method.h... no
checking for vm_core.h... yes
checking for iseq.h... yes
checking for insns.inc... yes
checking for insns_info.inc... yes
checking for eval_intern.h... yes
creating Makefile

make
gcc -I. -IC:/Ruby19/include/ruby-1.9.1/i386-mingw32 -I/C/Ruby19/include/ruby-1.9
.1/ruby/backward -I/C/Ruby19/include/ruby-1.9.1 -I. -DHAVE_VM_CORE_H -DHAVE_ISEQ
_H -DHAVE_INSNS_INC -DHAVE_INSNS_INFO_INC -DHAVE_EVAL_INTERN_H -IC:/Ruby19/inclu
de/ruby-1.9.1/ruby-1.9.1-p243 -O2 -g -Wall -Wno-parentheses -o breakpoint.o -c
breakpoint.c
gcc -I. -IC:/Ruby19/include/ruby-1.9.1/i386-mingw32 -I/C/Ruby19/include/ruby-1.9
.1/ruby/backward -I/C/Ruby19/include/ruby-1.9.1 -I. -DHAVE_VM_CORE_H -DHAVE_ISEQ
_H -DHAVE_INSNS_INC -DHAVE_INSNS_INFO_INC -DHAVE_EVAL_INTERN_H -IC:/Ruby19/inclu
de/ruby-1.9.1/ruby-1.9.1-p243 -O2 -g -Wall -Wno-parentheses -o ruby_debug.o -c
ruby_debug.c
ruby_debug.c: In function `ruby_method_ptr':
ruby_debug.c:141: warning: dereferencing type-punned pointer will break strict-a
liasing rules
ruby_debug.c: At top level:
C:/Ruby19/include/ruby-1.9.1/ruby-1.9.1-p243/insns_info.inc:660: warning: 'insn_
name' defined but not used
C:/Ruby19/include/ruby-1.9.1/ruby-1.9.1-p243/insns_info.inc:666: warning: 'insn_
op_types' defined but not used
C:/Ruby19/include/ruby-1.9.1/ruby-1.9.1-p243/insns_info.inc:672: warning: 'insn_
op_type' defined but not used
gcc -shared -s -o ruby_debug.so breakpoint.o ruby_debug.o -L. -LC:/Ruby19/lib -L
. -Wl,--enable-auto-image-base,--enable-auto-import -lmsvcrt-ruby191 -lshell
32 -lws2_32
ruby_debug.o: In function `fprintf':
C:/Ruby19/devkit/gcc/3.4.5/bin/../lib/gcc/mingw32/3.4.5/../../../../include/stdi
o.h:246: undefined reference to `__mingw_vfprintf'
collect2: ld returned 1 exit status
make: *** [ruby_debug.so] Error 1


Gem files will remain installed in C:/Ruby19/lib/ruby/gems/1.9.1/gems/ruby-debug
-base19-0.11.23 for inspection.
Results logged to C:/Ruby19/lib/ruby/gems/1.9.1/gems/ruby-debug-base19-0.11.23/e
xt/ruby_debug/gem_make.out

Any thoughts....?

Norbert said...

Thanks!

for newer versions:

the method debug_eval has changed since posting. At the end it should look like this now:

def debug_eval(str, b = get_binding)
begin
str = str.to_s
return "" if str == "$FILENAME"
max_time = 10
to_inspect = str.gsub(/\\n/, "\n")
@printer.print_debug("Evaluating with timeout after %i sec", max_time)
timeout(max_time) do
if RUBY_VERSION < "1.9"
eval(to_inspect, b)
else
Debugger::without_stderr { eval(to_inspect, b) }
end
end
rescue StandardError, ScriptError => e
@printer.print_exception(e, @state.binding)
throw :debug_error
end
end


Sorry if the code looks messy.

Giorgio Ferrara said...

Hello everybody and thank you for your comments.

@Laran: all the info I collected here are taken from this thread: http://www.jetbrains.net/devnet/thread/283957

@BDVS: I didn't reproduced you error fully. However I had a similar error when, editing the file fstab (point 2), I introduced wrong directory names. So pls check entries in that file. Be sure that each entry corresponds to a valid directory in your installation. Hope this help.

Ken Keller said...

Does this mean I must install gcc, bash, make on Windows7?

Pr. Silfar Goulart said...

Hi, I'm try, but:

Cannot connect to the debugged process at port 51095 in 10s:

Dumping and destroying process, when the debuggee process is running. You might try to increase the timeout. Killing...

Error Output:
C:/Program Files (x86)/JetBrains/RubyMine 2.0.2/rb/gems/rdebug-hack.rb:9:in `require': no such file to load -- C:/Ruby19/lib/ruby/gems/1.9.1/gems/linecache-0.43/lib/../lib/trace_nums (LoadError)
from C:/Program Files (x86)/JetBrains/RubyMine 2.0.2/rb/gems/rdebug-hack.rb:9:in `require'
from C:/Ruby19/lib/ruby/gems/1.9.1/gems/linecache-0.43/lib/tracelines.rb:12:in `rescue in '
from C:/Ruby19/lib/ruby/gems/1.9.1/gems/linecache-0.43/lib/tracelines.rb:8:in `'
from C:/Ruby19/lib/ruby/gems/1.9.1/gems/linecache-0.43/lib/tracelines.rb:6:in `'
from C:/Program Files (x86)/JetBrains/RubyMine 2.0.2/rb/gems/rdebug-hack.rb:9:in `require'
from C:/Program Files (x86)/JetBrains/RubyMine 2.0.2/rb/gems/rdebug-hack.rb:9:in `require'
from C:/Ruby19/lib/ruby/gems/1.9.1/gems/linecache-0.43/lib/linecache.rb:63:in `'
from C:/Program Files (x86)/JetBrains/RubyMine 2.0.2/rb/gems/rdebug-hack.rb:9:in `require'
from C:/Program Files (x86)/JetBrains/RubyMine 2.0.2/rb/gems/rdebug-hack.rb:9:in `require'
from C:/Ruby19/lib/ruby/gems/1.9.1/gems/ruby-debug-base-0.10.3/lib/ruby-debug-base.rb:3:in `'
from C:/Program Files (x86)/JetBrains/RubyMine 2.0.2/rb/gems/rdebug-hack.rb:9:in `require'
from C:/Program Files (x86)/JetBrains/RubyMine 2.0.2/rb/gems/rdebug-hack.rb:9:in `require'
from C:/Ruby19/lib/ruby/gems/1.9.1/gems/ruby-debug-ide19-0.4.12/lib/ruby-debug-ide.rb:5:in `'
from C:/Program Files (x86)/JetBrains/RubyMine 2.0.2/rb/gems/rdebug-hack.rb:9:in `require'
from C:/Program Files (x86)/JetBrains/RubyMine 2.0.2/rb/gems/rdebug-hack.rb:9:in `require'
from :34:in `require_relative'
from C:/Ruby19/lib/ruby/gems/1.9.1/gems/ruby-debug-ide19-0.4.12/bin/rdebug-ide:9:in `'
from C:\Ruby19\bin/rdebug-ide:19:in `load'
from C:\Ruby19\bin/rdebug-ide:19:in `'
from -e:1:in `load'
from -e:1:in `'

You can help me.