It was only last April when Laurent Sansonetti captured the imagination of the entire Ruby community with RubyMotion. For the first time Ruby developers were able to write apps directly for the iOS mobile platform using the language we all know and love. Now there is no longer a need to learn the archaic, verbose Objective-C language, or worse yet to learn to navigate the confusing myriad of windows and dialog boxes in the XCode IDE. We can just bring the magic of Ruby to iOS, using our favorite command line tools.
I was thrilled earlier this month when Laurent agreed to do an interview with me for RubySource. I would be able to learn more about RubyMotion directly from its inventor. Since I had so many questions, I’ve divided the interview into two posts. First today I’ll ask Laurent some basic questions: What is RubyMotion, exactly? What does it do? How should we use it? Is writing Ruby for iOS any different from writing a “normal” Ruby app?
Tomorrow I’ll post the second half of the interview, which will be a bit more technical: How does RubyMotion work internally? How does Laurent use the LLVM framework to compile Ruby code into a static executable? How does it differ from the way MacRuby and Rubinius work? I love learning about Ruby internals, and RubyMotion is certainly a unique and fascinating implementation of Ruby.
#INSPECT – the first conference ever devoted to RubyMotion
Q: Would you like to start by telling us about the upcoming RubyMotion #INSPECT2013 conference?
6 months after RubyMotion was released I had the idea of doing a small event, a one day conference, about RubyMotion. And then I just got busy with other things. I left that on the side and recently my friends from Phusion, who did a conference called BubbleConf in Amsterdam dedicated to startups, invited me to give a talk and it was great. I talked about the fear and depression before I launched RubyMotion (available here). Ninh Bui, a very good friend, actually organized the conference; well he got some help, of course. It’s kind of a big deal. Then I got jealous; I said: “I want to do my own conference too.”
Q: It sounds like a tremendous amount of work.
Yea, it’s not easy. At the same time I am not as ambitious as Ninh. Ninh did a really big show; he rented a very old venue, an awesome cinema in Amsterdam for 300 people. Mine is much simpler; I only want 150 people. Originally I wanted to do it in the US, because that’s where most RubyMotion users are. But then I told myself for the very first edition it should be pretty special, and I decided to do it here in Belgium.
Q: Why is that?
First, it’s easier for me to organize it. I wanted to do the first one as small as possible, to do something intimate, where people can actually talk to each other, can actually hack together. I’m not doing it for money, I think we will actually lose money on the first one. It’s all about having fun and trying to promote RubyMotion. Just having a conference is a great sign that the community is healthy. We’ll also have some activities for people who come with people to the conference: a chocolate factory visit, and also we’ll visit a brewery, where they make a very typical beer from Brussels.
We actually have kind of a long list of speakers. But at the same time these are very short talks, 30 minutes, and we have a lot of space between them. I also wanted a one track – just one set of speakers. Our speakers include people from the RubyMotion community, famous people such as Nick Quaranto (37signals) and Matt Thompson (Heroku), but also people less well known that have been doing amazing things in RubyMotion. So I think it’s going to be interesting.
How RubyMotion got started
Q: You used to work at Apple, is that right?
Yes, for seven years. MacRuby was my last project at Apple. It is open source, which is rare at Apple. It was kind of successful; at one point it was clear the management wasn’t interested any more in sponsoring MacRuby, so I had to make a decision: I could stay at Apple and work on something else, or I could quit the company and join another company or start my own company. I thought about it a lot and realized that I had a great opportunity to do my own company.
My kid was very young, four months old. We were living in California at that time but we wanted to go back to Europe. All the puzzle pieces were actually melting and it all made sense that I had to do the startup.
Q: Are you working with other people on RubyMotion?
It was only me for a long period of time, but four months ago I hired Shizuo Fujita; whose nickname is “Watson.” He is very popular in the MacRuby community. When I started on RubyMotion I really didn’t work on MacRuby any more. Watson took everything with the project; he was the biggest committer on the project. There are also two other people I would like to hire this year.
What is RubyMotion?
Q: What is RubyMotion? How did you get started with it? Where did the idea come from?
RubyMotion is a toolchain to do iOS development in Ruby. By toolchain I mean it’s a set of different components. First, RubyMotion is an implementation of Ruby for iOS. It’s a reimplementation of the Ruby language on top of the Objective-C runtime, and on top of the core frameworks of iOS. It means that in RubyMotion the object model is actually implemented using the Objective-C runtime. So in RubyMotion when you create classes, objects or methods, you are actually using the same runtime implementation of Objective-C objects, classes or methods. There is no bridge between the Ruby and Objective-C languages. In RubyMotion people can actually access the entire set of iOS APIs, which are implemented in Objective-C natively, without using any sort of middleware.
Ruby 1.9, JRuby and Rubinius all run your
code using a virtual machine
Q: They’re all part of the same working system?
Exactly. The Objective-C runtime is actually a very small C library that people can use, and that’s what we do. A RubyMotion application calls into the same runtime API as if the application were written in Objective-C. Also, this implementation of Ruby is using the core frameworks of iOS to implement some of the built in classes.
For example, the String class in RubyMotion is implemented as a subclass of NSMutableString from the foundation framework. From the Ruby user perspective there are very few changes. Under the covers it’s actually using the same behaviors as an Objective-C string. This means if you create a string in Ruby and then you pass that string to an Objective-C API that expects a string there’s no conversion; we just pass the object as is. This is what we call the “unified runtime.” We use the same Objective-C runtime for the object model, and we use the core frameworks for building classes.
RubyMotion, however, statically compiles your code into
native machine language that runs on the target device
Q: You had to write the support for Ruby methods, like “upcase,” which are not part of Objective-C?
Yes. RubyMotion is actually a flavor of MacRuby, which I created at Apple, about 5 or 6 years ago. That design comes from MacRuby.
Q: What else is in the RubyMotion toolchain?
RubyMotion also has a static compiler. This compiles Ruby into optimized machine code right away. It links with this implementation of Ruby that we wrote. This is what RubyMotion is about – it’s a runtime, an implementation of Ruby, and it’s also a compiler.
RubyMotion also includes a runtime component that implements
Ruby features which don’t exist in Objective-C
Q: So what goes on the device is the Objective-C runtime, the Ruby runtime, and that’s it?
Yes, that’s it. We use the Objective-C runtime for the object model, and then we have this Ruby implementation runtime that we link against statically, which is about 1MB. This contains all the existing classes, like String, Array, Hash, etc., and also it implements all the Ruby language features that don’t exist in Objective-C. For example, Objective-C doesn’t have the notion of mixins. We have to implement mixins by ourselves. Also, in Objective-C you cannot set instance variables dynamically to a class so we also have to work around that.
RubyMotion vs. MRI
Q: Which version of Ruby is RubyMotion based on?
We’re actually following Ruby 1.9. RubyMotion is a fork of MacRuby and MacRuby was for a long time trying to follow the RubySpec project. RubySpec is an executable set of specifications for Ruby. I think it was extracted from the Rubinius project. MacRuby was trying to follow that to make sure we were complying to the specifications of Ruby. At that time, I think the latest version of RubySpec was 1.9.1. Then we forked MacRuby for RubyMotion and since then we haven’t looked at RubySpec any more.
In RubyMotion we actually removed features from Ruby, since it is statically compiled and there are certain features of Ruby that we just cannot expose.
Q: If I’m a Ruby developer, if I write Ruby every day and I start to use RubyMotion, what would I notice to be different?
I think the biggest difference and also one of the only differences is that in RubyMotion there is no “require” statement.
Q: What does that mean? How do you include other libraries?
Because RubyMotion is statically compiled, the build system has to know ahead of time at build time all the files of the project. It has to build an executable ahead of time. So we can’t just require files at runtime.
Q: It’s analogous to a C program using includes, having a Makefile, that sort of thing?
Exactly. And the build system right now is kind of smart. When you create a RubyMotion project you have a directory called “app.” And in the app directory you can just create .rb files; having one file per class is a good way to structure your project. Then the build system will take all these .rb files and try to detect dependencies between them. For example, in one file you create a class Foo and then in a separate file you create a class Bar that inherits from Foo. The build system will detect that and it will compile the first file before the second file. At runtime when the program starts, the class Foo is created before the class Bar.
Because of this feature, people don’t usually need to require files.
Q: …it just happens automatically?
We could actually have a require method that could be used as a compiler hint. But I’m not happy with this idea because require in Ruby is a method of the Kernel class; it’s not a language keyword. Since it’s a method, you can pass a variable to it. It doesn’t need to be an immediate type. You can require X, which X points to a string that has been defined before. This means that the compile would have to deal with these edge cases and it doesn’t sound like a good idea.
So right now the build system will just parse the code and try to set the dependencies for you. Require in RubyMotion right now raises an exception. That’s the biggest difference between traditional Ruby and RubyMotion. Other than that, the differences are quite small.
The second difference is that in RubyMotion the “eval” method of a string doesn’t work. Supporting eval would mean that we would have to ship an interpreter for Ruby, an interpreter inside the application. This is something that is not totally clear regarding Apple guidelines for iOS.
Q: They wouldn’t allow you to do that?
You can actually ship an interpreter, but you cannot download code. I was just afraid that if we shipped an interpreter in RubyMotion Apple would stop approving RubyMotion applications.
Q: So by removing eval you can tell them you didn’t do that…
Also the iOS hardware, especially the old ones, are not that fast. They used to be slow, actually. Interpreting code at runtime was just not a good idea.
Q: Are the related methods also not valid, like instance_eval, class_eval, things like that?
These are working – everything else should be working. You can call all the metaprogramming stuff.
Q: Are these the only two differences, then?
That’s about it; except there are a few other minor differences. Here’s a list:
Require isn’t supported because of the build system,
Eval of a string doesn’t work,
Proc#binding has been removed, and
Overriding of operators on Fixnum and Float is disabled.
[ Author’s note: Laurent and I discuss Proc#binding and operator overriding in part 2 of this interview. ]
Why isn’t RubyMotion open source?
Q: Is RubyMotion open source? Or proprietary?
The proprietary components are the runtime and the compiler. The build system is written in Ruby and is open source, which is a great thing because a lot of people like to hack the build system.
Q: So the real special technology you’re providing customers in RubyMotion is the compiler?
Yes, the compiler and the Ruby implementation (runtime). The Ruby implementation is closed source. I’ve been really thinking hard about that: should I open source everything, or should I open source a piece of it.
In order for the project to be viable, I need money. If it were free, open source, I would need to find sponsors. I don’t really like sponsors, since they can let you go at any time, and then you need to find other sponsors to keep the project alive, or you need to do another kind of work on the side. And then I also realized that if RubyMotion were free and open source, then it wouldn’t mean that the project would actually grow faster. MacRuby has been open source since its inception, since the beginning, and I think we only had four people over six years who actually contributed code to the runtime or to the compiler.
My worry is that if RubyMotion were open source, I’m not actually sure if it would help, because RubyMotion is mostly used by Ruby programmers. And Ruby programmers are not very familiar with C compilers and virtual machines.
Q: It’s not like Rails, where they can go in and easily fix things or add new features. No one is going to go into your compiler and change something there.
Exactly. So with RubyMotion I’ve tried to open source everything that is Ruby, which is great because we get a lot of patches. I can see we actually have more pull requests, so I should actually check them. I’m very lazy.
Q: Sorry! I’m taking all your time…
So I think this is a great compromise; we open source what can be, and this way we ask for a financial contribution from users so we can build a business around it. Also I don’t want to get investments for this startup. My goal is to run a fully bootstrapped company, and there are no external investors.
Q: That’s fantastic.
And I think this is the way this should go, because I want the product to be alive for years, and once you take an investment you’re not really in control of the company any more, because most investors want a return on their investment between 3 and 5 years.
Q: This way you can do what you want to do, on your own schedule.
Exactly. For me the only way to do that was to actually charge for it.
Q: What’s next for RubyMotion?
Right now it’s hard, because RubyMotion is growing so fast. It’s only been 8 months since we released it. We’re at the point now where we have a lot of different options. We can do a lot of things, a lot of significant features for the platform. At the same time, we are limited in terms of human resources. So we have to make a decision.
What we’ll probably do is improve the toolchain. The toolchain right now is completely based on the command line, and it works for most users. But at the same time some people really like IDEs, and we’ve been working with JetBrains. RubyMine has great RubyMotion support; you can actually debug RubyMotion code inside of RubyMine and it’s great. We want to keep working with them so we can write an IDE for RubyMotion users.
A lot of users have also been requesting RubyMotion to be ported to other platforms.
As I mentioned at the top, keep an eye out for the second half of this interview tomorrow on RubySource. Laurent and I will explore how RubyMotion actually works internally.