Having a nice user interface to set breakpoints, step through execution and inspect local variables can be just what you need when chasing a hard to fix bug in your Ruby C extension. If you're on OSX you're in luck, because this post is about how you can import your C extension code as an XCode project and enjoy the benefits of the debugger and other developer tools.
Note: I'm using XCode v5.1.1 in this tutorial
1. Get the code
First of all you need to get the code you want to debug. For this example,
I'm going to use Codemancers' Rbkit,
a Ruby profiler which comes with a C extension.
I've cloned the gem from its github repo ( Repo:
and as per the README, set the RBKIT_DEV env variable so that the Makefile
is always generated with the
-g CFLAGS for debugging.
ruby extconf.rb inside
ext directory to create the Makefile. XCode
can take it from here.
2. Create a new XCode project
File -> New -> Project and choose
External Build System from
Fill in some product code, say rbkit:
ext directory of the C extension, this is where the XCode
project will be created :
3. Build the project
Now the project is set up and a "Target" is created which is used to build
the project. Under
External Build Tool Configuration (which should be there
on your screen at this point), choose the
ext directory of Rbkit as the
directory and uncheck
Pass build settings in environment checkbox :
Now you should be able to press ⌘ cmd+B and build the project successfully.
4. Prepare an executable
You'll need to give XCode an executable so that it can be run using a debugger. For us the executable is going to be the "ruby" executable.
Create a symlink to ruby at
ext directory :
~> ln -s `which ruby` ruby
Now we'll configure the "Run" command of XCode so that it runs our
Product -> Scheme -> Edit Scheme. For "Run" scheme (which you can
select on the left hand side), under
Other and choose
Options tab and enable
Use custom working directory and choose
ext as the working directory:
Arguments tab and click on
Arguments Passed On Launch to
add the following argument to ruby executable :
Now you should be able to press the Run button
( or ⌘ cmd+R ) to run the script using Ruby.
Once the script is running, you should be able to see that Memory usage keeps
increasing steadily under the Debug Navigation (⌘ cmd+6).
That's because our
experiments/using_rbkit.rb script just keeps creating
new objects in Ruby.
5. Start debugging
Now that the project is set up and we're able to run the code using XCode, we should be able to map the source files for the executables and use the debugger to add breakpoints and step through the code.
1. Add source files
Select Project Navigation ( ⌘ cmd+1 ) , click the
+ button on the bottom left corner and select
Add files to "rbkit".
You can now add the source files which you want to debug. For now, I'm just adding
2. Set breakpoints and inspect variables
Let's add a breakpoint on
This line gets called everytime a new object is created to serialize the
object's classname. Once we "Run" the project, execution should pause at
this breakpoint. Now we can "Step into" the
( using F7) to see the classname being passed into it. At the bottom
on the left half, we can see the variables and their values and on the right
half is an interactive lldb console.
frame variable string will return the
value of the
char * string argument of
pack_string function where we have
stepped into. Check it out :
Good job if you've reached this far. You should be able to take this forward and unleash mad debugging skills upon all C extensions.
- We cloned the C extension source, created the Makefile.
- Set up XCode project and built the project.
- Ran our test script using the ruby executable from XCode.
- Added source files and tried out some debugging.