Laurent Sansonetti on Writing Ruby Apps for iOS with RubyMotion

Recorded at:

Bio Laurent Sansonetti is the founder of HipByte, a software tools startup that recently launched RubyMotion, a toolchain for iOS development in Ruby.
He worked at Apple for 7 years as a senior software engineer, on both iLife and OS X. A long time Rubyist, he created and still maintains the MacRuby project. In a previous life, he worked on IDA Pro and was an active contributor to RubyCocoa and GNOME

GOTO Aarhus is the enterprise software development conference designed for team leads, architects, and project management and is organized by developers, for developers. Important topics are presented by the leaders in our community. The conference concept is to present the latest developments as they become relevant and interesting for the software development community.

I’m a Belgian software hacker. So my name is Laurent Sansonetti and I’ve been contributing to the Ruby community for a long time but I was working for Apple for about seven years and I’m mostly known for having created the MacRuby Project, which is an implementation of the Ruby language for the Mac. Recently I decided to quit Apple to do a startup and to do a product and that product it’s actually a board of MacRuby for iOS, it lets you do applications for iPad or iPod, iOS platforms, but using Ruby, so we are very excited about that.

So I was at University, it was in 2001, I’ve always been a C programmer so I like system programming, low level programming, programming languages and virtual machines, but I really had this dream of using a higher level language for application development, because C is very low level for that and at that time Perl was my favorite language, I really loved Perl. And then, one day some guy told me: “Well you should try Python, it’s really nice it’s better, it’s cleaner”. And I say: “Yes, why not”, and Python was very big in Belgium at that time because one of the local university actually give free course on Python and free book, and actually one of the guys I think is part of the Python core team something like that, so it was actually big. So everyone was using Python and I say: “Perhaps there is another language to try”, and some friend told me: “You should try Ruby”, and Ruby was absolutely not popular at that time.

It was five years before Ruby on Rails was launched, so nobody knew about Ruby except in Japan, and few people in the US, and it as that book called ”Pickaxe Book” which was the very first English book about Ruby, it was made by the Pragmatic Programmers, and that book was freely available on the internet, so I grabbed a copy and I started reading both Python and Ruby documentation, and in the end I realized Ruby is better, it feels cleaner, the OO model is more native to the language. So I decided to go with Ruby and my dream was really to make sure that you could use Ruby for application development, really wanted that, and at that time I was using Linux with the Gnome desktop system, I was contributing to Gnome also and I say: “We should definitely be able to use Ruby to write Gnome Apps”, so I joined the Ruby Gnome 2 Project, which actually provides a set of Ruby wrappers for the APIs. And I contributed wrappers, up to the point where had our first big Gnome Application written in Ruby – it was called Alexandria, it was a book manager, and it was quite popular at that time. And then Apple contacted me to, they wanted to hire me and so I have to give away my Linux Desktop to get a Mac.

So I had to learn Objective C and I started working for Apple applications, starting working on iCal the version of Leopard. I still had Ruby in my mind, I said: “It will be great, we could use Ruby to do Mac applications and there was this project around, RubyCocoa which was more or less the same thing as Ruby Gnome 2 source, some sort of a middleware wrapper between the Cocoa API’s and Ruby virtual machine so you could use the Cocoa API’s from Ruby. So I joined that project and I started contributing and I eventually maintained the project for two or three years and I rewrote a big part of the project to be more efficient, to have better performance. Actually RubyCocoa ships with Mac OS X since Leopard. Since Leopard RubyCocoa is a part of the system, it was one of my projects at Apple.

We wanted to provide more languages around all API’s so the people could use all the languages. In Leopard we added PyObjC and RubyCocoa it’s PyObjC of Python version and then it was 2008 before the Christmas break and I was sitting up at the cafeteria and one of the senior vice president of software engineering Bertrand Serlet, a French guy, I was having a coffee with him and he said: “Well, how’s Ruby doing?” And I said: “Well we have this new RubyCocoa Project, but honestly it’s not good for performance because it’s a bridge and we try to build a big application in it and you could see that there were performance issues because objects needs to be translated between two runtimes, we have memory issues and we had to have a huge set of caches because it’s a bridge.”

And you know there are the two more difficult things in software engineering are naming things and invalidating caches and so we had so many caches and it was so hard to maintain and Bertrand said: “Why don’t you just rewrite Ruby on top of Objective C, this way you don’t have the bridge anymore and it’s like a no brainer”, he said. And I said “Yes, but it’s way too hard and I really don’t have the time to do that.” And that Christmas break was when I said “Let’s have a look” and I grabbed the Ruby 1.9 source code, because at that time 1.9 was not really stable yet but it was where most of the people were hacking, so the codebase was cleaner than the 1.8 version of Ruby. So I took that codebase and I started to plug the Objective C runtime. The first thing I did I think it was to rewrite the class system so that it would use Objective-C classes instead of the Ruby representation of classes, so that we would add this so a Ruby Class would equal an Objective-C Class.

Then it actually worked very quickly so I was really surprised. I made a very small prototype and I showed it to Bertrand and he said: “Wow, this is awesome!” I asked him if I could work on this and he said: “Yes, you can”, and so we started that project and we named the project MacRuby and that was in 2007 and for about three years MacRuby has been growing. First it was really a port of Ruby 1.9 for Objective-C, then we started rewriting parts of the project because we wanted a better String class, a better Array class, a better Hash class because we wanted this classes to be based on Foundation classes that were the Objective-C equivalents for this types. So we started rewriting the project then we removed the interpreter and we replaced it with a LLVM based machine.

So the Ruby source code is actually translating to LLVM IR, the language of the LLVM compiler and then we could just in time compile it or ahead of time compile it and it was much, much better. That was in 2006 I think, so two years later. Right now with MacRuby we are almost at version 1.0, it’s very, very stable. We just lack the time to make a release for the 1.0 tag, but it has been around for about three or four years. But people really wanted to use MacRuby for iOS Development and MacRuby is really based on Mac technologies like Objective-C garbage collector which is the memory management system of Objective-C and that part is not available on iOS. So MacRuby could not run on iOS, also MacRuby was using LLVM just in time compilation and JIT compilation is prohibited in iOS for security reasons, you can’t mark a memory page for execution. And so MacRuby could not run as-is on iOS and also people started to ask about it, we want MacRuby for iOS, and at Apple there was no interest in doing that at that time.

Eventually I decided to say: “Well, I always wanted to do a startup” and it was my 7thyear at Apple, so it’s actually a long time, seven years in a company, it’s like a PhD in a way, it’s very long. So I said: “Well, I want to do a startup and I know that there are people who would be interested in doing iOS Development in Ruby, so why not doing this as a product?” I tried it and it’s actually working great, the product is called RubyMotion so it’s really a port of MacRuby for iOS, it has a lot of new things, it has a static compiler that uses one hundred percent static compilation, so there is no interpretation, no just in time compilation on the device. It has a new memory management model that doesn’t use the Objective-C GC so it’s completely brand new and it has a Rakefile based system, so everything is based on the command line. So in MacRuby you need to use XCode for application development. What we learned in four years is that Ruby people hate XCode, they’ve really have a hard time using XCode because it is very complicated and Ruby support in XCode is very bad.

So for RubyMotion I said “I don’t want to make the same mistakes, so let’s not use XCode let’s start from fresh, just a very simple command line", Rakefile based toolchain, and then people can use their favorite text editor, so people can use vim, TextMate, Emacs, even RubyMine where are talking with JetBrains at the moment to support Ruby Motion on RubyMine. It’s very different from the way that other their mobile platforms, force you to use their own IDE for this kind of things. In RubyMotion we really want that people to use their favorite text editor and that was it, we launched the project 4th of May and it was a great success, I really didn’t expect that.

You need to get XCode installed on the computer, you don’t need to launch XCode at all, but you need XCode because XCode comes with the iOS SDK, so RubyMotion needs access to the SDK, so it needs to be installed somewhere on your machine and the best way is to install XCode. These days XCode ship has a .app bundle, so everything is inside the bundle including the command line tool, so you really need XCode so that RubyMotion can use the command line tools to build and to link your applications. But this is the only thing you need, you don’t need a LLVM, RubyMotion ships with this own version of LLVM it’s all Bundler. So you just need XCode and of course an iOS device and if you want to push your application to the device you need to be part of the Apple Developer Center, because this way they give you a certificate that you can use to codesign your application for your very specific device, but that is all, so XCode needs to be part of the Apple Center.

Yes, the great thing about RubyMotion is that we actually statically compile everything, so when you get the backtrace of a crash, a RubyMotion crash, it is exactly the same back trace as an Objective-C app except that certain frames in the backtrace, will be functions, Ruby functions that represent Ruby methods. Since the latest release 1.24, the RubyMotion compiler embeds DWARF metadata for your code inside the binary, so it means that we use the same debugging information that Objective-C or C or C++ to provide contextual metadata around your code, like for instance, we know that at this very specific offset of the code corresponds with this line and this file in your project. So when you get a backtrace we know where this is exactly, where we are exactly. We use the same technique the same information.

So the great thing is that if you add GDB or LLDB or any debugger to a RubyMotion application and you ask for a backtrace, it will work out of the box, because we use the same DWARF metadata, so means that you get a backtrace, you will see eg UIView if you break inside the drawing method, and then at very end you will see your Ruby file and line even the name of the Ruby method. So the debugging experience is probably the same as Objective-C. It doesn’t mean that is great, because it’s very low level and Ruby programmers really prefer a much higher level debugging experience. In Ruby on Rails, there is a very nice debugger, which is very nice. It lets you introspect things more, I have not really investigated it yet but we want to have the best debugging experiences possible.

Right now you can use GDB and it works if you know this kind of thing but most Ruby developers are probably not going to use GDB, so we are going to build a high level debugger on top of GDB, that will send the same commands to GDB under the cover but it will let you do more interesting things, and when it comes to profiling you can use instruments also, it works because we use the same memory allocator as Objective-C. When you create a class in Ruby it’s an Objective-C class and when you create instances of that class these are Objective-C instances, so it means that if you profile using Instruments, you will see your Ruby classes there. If you set up Instruments you have the call stack for every allocation of Ruby specific object, you will see the Ruby stuff there also similar to GDB works. But again it’s not perfect I think, if you really know Instruments or GDB for Ruby, we want to build a higher profiler also. This is something that we probably do in the future.

iOS doesn’t support garbage collection, the Foundation framework is based on Autorelease pools which is different garbage collection, so it’s a form of garbage collection, when you think about it, you have the retain count system where every object has a retain count, when you get a reference of an object you increment the retain count using retain message and when you don’t need the object anymore you send the release message, and then at the very end when pool . is destroyed, the object is collected if it’s marked for release of course, but that is a different question. But it’s a form of garbage collection and when people said that there is no garbage collection on the iPhone it’s not true, it’s a form of garbage collection, it’s sort of delayed retain based garbage collection system.

Since ARC, which is a new mode in Clang which will insert the retain/release messages for you at compilation time, so you can say it’s a form of garbage collection. In the case of RubyMotion we can’t use the Objective-C GC on the phone because it doesn’t exist which is really a shame because the Objective-C GC is awesome, it’s multithreaded generational garbage collector, everything happens on different cores.

It would have been great to have it but we don’t have it so what we do is that we do exactly like Clang, but except that at compilation time we do it at different times, so we actually do the retain and release messages for the user, so they don’t need to think about that. And we use the same infrastructure, the same Autorelease pool system in place, which means that your objects in Ruby Motion will be collected when the nearest Autorelease pool is destroyed. So if you write in a typical iOS App you don’t even need to think about Autorelease pools because methods are short and when you leave a method you just enter the run loop, and in the run loop it already triggers Autorelease pool destruction. Most of the time people don’t need to think about that.

Right now in RubyMotion there is no support for cycles, so cycle is basically an object that has a reference to another object and vice-versa. Cycles can be very easy or can be very big, I mean you can actually have a huge chain of references, and right now Ruby Motion doesn’t support that. So, if you have a cycle both objects will leak. ARC does the same, ARC doesn’t support cycles, but this is something we want to do in the future, so we really don’t want programmers to think about cycles and keep the object graph in mind. So we are going to introduce support for cycles in the future. We want the support to be as efficient as possible, so it can’t slow down allocations, it can’t slow down garbage collection of Autorelease pool objects and it can’t use more memory then we already do. So it’s very challenging but we have a couple of plans that we are working on, and we probably pick the best one.

It’s actually a very good question, the project is very young, it’s only five months old, but as far as we know we can see that most projects are actually using third party RubyMotion Libraries. In RubyMotion we can’t use Ruby Gems because RubyMotion implements a dialect of Ruby and those features are not available and also it’s a statically compiled version of Ruby so there is no require statement in RubyMotion. All the files must be provided at build time, so it means that you can’t just grab Ruby code and it will not work, you need to tweak it a little bit, but once RubyMotion was released, the community started to create interesting projects around it and there is the Bubblewrap project which is a set of wrappers around iOS. So for instance you have Ruby DSL to deal to HTTP Post and Get messages, you also have one to do JSON parsing and creation.

I think that most RubyMotion projects probably use this project Bubblewrap because it gives you wrappers for free so it’s a no brainer and then there is the Sugar Cube Project which is more like a DSL to create UIs, you have the Formotion project which lets you write preference windows, in iOS when you go to the system preferences. It looks like a table with patterns, it’s more like a dialog UI, it’s actually very hard to write it in Objective C, I mean using the iOS APIs because you need to write a custom UI. In Formotion is actually very easy, it’s a simple Ruby hash that you pass to the method and creates the UI for you. Most people use that when they want to do a preference dialog for their app. I think that the Ruby Motion ecosystem is growing. Most projects will probably use at least one or two libraries.

I think there is one that is very interesting, it’s called Everclip, it’s an application for Evernote so it lets you clip text images, anything from the browser and it sends them to Evernote, so it’s all written in RubyMotion, I think it’s even the first commercial application written in Ruby Motion, so you need to purchase it and I highly recommend it if you are a user of Evernote. These guys were actually selected to be part of the some sort of Evernote cup, the Evernote company organize some sort of meeting in San Francisco, so they flew. the developers of Everclip there and they want the price, they want 20.000$ I think, so using the RubyMotion app and we are super excited. Another very interesting app is called Cabify, it’s an application made by a startup in Madrid, Spain, that lets you order taxies using your phone, you can basically ask for a taxi to came pick you up based on your location, knows where you are, so they are using RubyMotion for that. Both applications are based written in RubyMotion, there is also an application in every Mercedes Benz, they use Mercedes for the taxies, so the taxi has an iPhone that is notified once someone asks for it, so both applications the consumer app and the taxi app are written in RubyMotion. That is the second success story.