…It was sunny Friday`s morning. My friend and I drank coffee and decided to take a look at Rubinius 2.0.0-dev. We hoped it would be enough easy to install. But we didn`t expect it to have some problems with rbenv and RubyMine as well:)
Rubinius is an alternative Ruby implementation. In Rubinius as much of Ruby as possible is implemented in Ruby language itself. So it`s very helpful and interesting to see how some parts of Ruby core work. And it`s more interesting than digging into C code of MRI (but of course it`s helpful in some cases too). Another thing you should know - Rubinius is a thread-safe interpreter. So you may use Celluloid or Puma server with full support of threads.
Installing Rubinius 2.0
You’ll need another version of ruby already installed as well as rake for installing Rubinius 2.0. Don`t use another version of Rubinius for installing this one:)
Also libyaml must be installed. I use homebrew for doing this:
$ brew install libyaml
Get the latest HEAD for rbx-2.0.0-dev and install it:
$ git clone https://github.com/rubinius/rubinius.git $ cd rubinius $ ./configure --prefix=~/.rbenv/versions/rbx-2.0.0-dev --enable-version=1.8,1.9 --default-version=1.9 $ rake install
Rubinius stores gem`s bin files in distinctive folder, so rbenv doesn`t correctly work with them. Fortunately, a plugin exists for fixing that.
$ mkdir -p ~/.rbenv/plugins $ cd ~/.rbenv/plugins $ git clone https://github.com/collinschaafsma/rbenv-rbx_2.0.0-dev_fix.git
Now Rubinius is available via rbenv:
$ rbenv shell rbx-2.0.0-dev $ ruby -v rubinius 2.0.0dev (1.9.3 72207d94 yyyy-mm-dd JI) [x86_64-apple-darwin12.1.0]
This is a long story… :)
We had just installed Rubinius and went to Settings -> Ruby SDK and Gems (RubyMine version 4.5.2). Unfortunately it couldn`t find RubyGems for rbx-2.0.0-dev. It looked strange, so we went to console to make sure:
$ rbenv shell rbx-2.0.0-dev $ gem list *** LOCAL GEMS *** actionmailer (3.2.8) actionpack (3.2.8) activemodel (3.2.8) ...
OK. Let`s have look at Rubinius folder:
$ cd ~/.rbenv/versions/rbx-2.0.0-dev/bin $ ls -la total 32840 drwxr-xr-x 10 stanislav staff 340 Aug 28 18:41 . drwxr-xr-x 8 stanislav staff 272 Aug 28 18:41 .. lrwxr-xr-x 1 stanislav staff 3 Aug 28 18:41 gem -> rbx lrwxr-xr-x 1 stanislav staff 3 Aug 28 18:41 irb -> rbx lrwxr-xr-x 1 stanislav staff 3 Aug 28 18:41 rake -> rbx -rwxr-xr-x 1 stanislav staff 16781972 Aug 28 18:41 rbx lrwxr-xr-x 1 stanislav staff 3 Aug 28 18:41 rdoc -> rbx lrwxr-xr-x 1 stanislav staff 3 Aug 28 18:41 ri -> rbx lrwxr-xr-x 1 stanislav staff 3 Aug 28 18:41 ruby -> rbx -rwxr-xr-x 1 stanislav staff 297 Aug 28 18:41 testrb
How interesting! There are one God File
rbx and many symbolic links to it. As you may know,
argv contains the actual arguments, starting with index 1. Index 0 is the program name. So Rubinius looks at
argv and determines what we want it to be. Well, it`s a good idea.
We made separate folder for experiments:
cd /tmp mkdir rbx cd rbx ln -s /Users/stanislav/.rbenv/versions/rbx-2.0.0-dev/bin/rbx ruby
Then we went to Settings -> Ruby SDK and Gems again and saw that RubyMine resolved symbolic links. So we changed symlink to hardlink:)
rm ruby ln /Users/stanislav/.rbenv/versions/rbx-2.0.0-dev/bin/rbx ruby
I decided to watch how RubyMine ran
gem command and created simple
gem file which sniffs all commandline arguments of each call. I probably could use
fs_usage or another monitoring tool, but I didn`n want that. Looking ahead, it was a right solution;)
1 2 3 4 5
Run RubyMine and watch at
Hm, seems legit. Maybe we should sniff also
ruby calls? Just copy and rename
script8027539471226326548.rb script5012912298001198018.rb -v script8063238159134301426.rb -v script8764279234205520073.rb -v script3430463985826171909.rb script2853497228306159189.rb -x, /private/tmp/rbx/gem, environment, gempath -x, /private/tmp/rbx/gem, environment, gempath -x, /private/tmp/rbx/gem, environment, gempath -x, /private/tmp/rbx/gem, environment, gempath -x, /private/tmp/rbx/gem, environment, gempath
Here is the problem caused by RubyMine. It tries to run
gem as a ruby file. Actually
bundle and other gems binaries in MRI are ruby scripts. But in Rubinius, as you may see,
gem is a symlink to rbx itself.
Our solution is simple. We made ruby script which forwards all calls to normal
cd /Users/Stanislav/.rbenv/versions/rbx-2.0.0-dev/ mkdir rubymine cd rubymine ln /Users/stanislav/.rbenv/versions/rbx-2.0.0-dev/bin/rbx ruby touch gem subl gem
1 2 3
And then let RubyMine go to this
~/.rbenv/versions/rbx-2.0.0-dev/rubymine/ folder. Enjoy!:)
Unfortunately, RubyMine IDE debugger doesn`t work with Rubinius 2.0 now. We hope they will fix that in the future. It would be totally perfect if this IDE debugger worked with rbx. Anyway you`ve got all refactoring tools, code navigation and other sugar of RubyMine.
But there is a brutal way to debug Rubinius - console debugger:) Just put this code where you want to start debug session:
You will get used to it quickly. Here is the list of debugger`s commands:
debug> help help: Show information about debugger commands b, break, brk: Set a breakpoint at a point in a method tb, tbreak, tbrk: Set a temporary breakpoint d, delete: Delete a breakpoint n, next: Move to the next line or conditional branch s, step: Step into next method call or to next line ni, nexti: Move to the next bytecode instruction f, frame: Make a specific frame in the call stack the current frame c, cont, continue: Continue running the target thread bt, backtrace: Show the current call stack p, eval: Run code in the current context dis, disassemble: Show the bytecode for the current method i, info: Show information about things set: Set a debugger config variable show: Display the value of a variable or variables