Ruby dominates the web: running popular sites like Github, Heroku, and Living Social. But why should web developers get to have all the fun? Wouldn’t it be great if game developers, embedded systems engineers, or anyone else could use the beautiful syntax of Ruby in their C programs? Lucky for us, that’s exactly what mruby plans to do.
The latest Ruby implementation from Matz is hoping to get big by going small. The goal of mruby is to run on any device while maintaining a super small footprint. Pretty ambitious aspirations since running a regular ruby (MRI/cRuby) processes could take up 20mb or more of memory just to get started. So mruby sounds pretty interesting, but how can we get it to a point where we can hack on it?
Follow along as we compile mruby from source and get it running on your computer. Before we can run mruby we’ll need to download the source and compile a binary, but what exactly is a binary?
What is a Binary?
A binary file is any file that is not a text file. Pretty simple, but we care about a specific kind of binary file. These are full functional programs that do not require installers and can be run directly by your computer. You already have quite a few of these binaries on your computer right now, but you’ve likely never thought of them that way. If you have ruby installed on your system, it is a binary. You can run the command
which ruby to get the location of the binary.
Note: Your output will be different from mine.
Once we know where the file is stored you can run it by just calling its full path on the command line:
You can use the full path to the ruby binary to run anything just like you would using your regular
So, now you see that
ruby is a binary on your machine, how do you go about making a binary and why is it even required?
Binaries, Who Needs em’?
While you might not care too much about what operating system you use or what architecture your CPU is built on, your software needs to know these things. Software written in a human readable language needs to be compiled to something your computer can run. Many times it can be easier to give someone source code and have them compile it on their own machine than to have to pre-compile binaries for all the different architectures out there.
If you’re on a Mac and you’ve ever used the homebrew library to install software like postgres:
Then you’ve compiled source code into a binary file. We can peek inside another brew formula to get an idea of how this is done. Take a peek inside the brew formula for wget a library for retrieving files over http:
Once open, you can see in homebrew’s DSL the url where we get the source code:
Wget is a library written in the C programming language. Once you have downloaded the source you need to configure it for your computer and then run the compile scripts so it can run on your machine. You can see where homebrew configures and installs the software:
Once the system has completed running these commands, it will produce a binary file compiled to run on your machine. This file can be used straight from your system. Distributing source code is much easier for code maintainers. It means that if you develop a new operating system or CPU architecture you still have a chance of compiling the code to something your new machine can understand. If you are building open source libraries it also makes it easier for people to modify your code, try out the modifications and then hopefully push any fixes or updates back upstream. Compiling binaries might not be as easy as drag and drop, but it is much more flexible.
So now you know what a binary is, and why it’s important. We’ll quickly cover the
PATH before we start compiling anything.
Walk the PATH
We’ve seen how we can call a binary directly using the full path, but that’s pretty messy. Is there a way to shorten that command so we can call:
Without having to specify the full path to the binary:
*Nix based systems, such as thie Mac, fix this problem by allowing us to store a list of directories that the operating system will search to find a binary with the same name. You can almost think of it as
method_missing for your OS. When you run
It will go down the list of path’s until it finds one that has a binary called
ruby, then it will execute it. You can take a look at the directories already in your path by running:
echo is like
print in bash (your command line). Here we are printing out the variable
PATH, the dollar sign in front tells bash that we want to evaluate the value of the environment variable
In the output you will get different paths separated by a colon
: when I run this command I get something like this:
You can see that the first path to my ruby library located in
/Users/schneems/.rvm/rubies/ruby-1.9.3-p194/bin is the first part of the path. When I execute the command
$ ruby, my operating system will look at that path first for a binary file called
ruby to execute. If it can’t find it it will continue to the next path until it can find the file.
So this is all interesting and everything, but what about mruby?
Let’s download mruby source so we can compile it for our machine.
Go to the mruby Github page. From we can grab the git url to clone the source code to our computer.
Note: mruby is in Alpha release and these instructions may vary. For the up-to-date information visit https://github.com/mruby/mruby/blob/master/INSTALL
Now that you’ve got the source code, you’ll need some way to compile it. To do this we will use Bison on your machine.
Install Dependencies: Bison
Visit http://www.gnu.org/software/bison/ then find the link to the the downloads. Look for the highest version number, and click on the file that ends in
.tar.gz this indicates that the file was tar)’ed up and then gziped. This is done to keep the size of the download small. If you wanted to do this programmatically you could use the
wget command we looked at earlier or
curl -O along with the url.
After downloading the file, you should be able to double click it on a mac and it will be automatically unarchived. If you’re on a command line kick, you can use the
tar command to unarchive the file
Now that we’ve got Bison on our computer, guess what…we’ll need to compile it! It sounds scary but it’s not.
Navigate to the directory where the bison folder is. For me it is in downloads:
The version of Bision I’m using is
2.6 so I’ll
cd into that directory:
Note: Your version number may be different.
Now you will want to run
Note: You’ll see lots of text fly by when you run these commands. I like to make sure I’m in a public place when compiling binaries since it looks like hackers do on TV. Then when it’s done you can slam your laptop shut yell “they’re on to me” and run out!
If you don’t get a bunch of error messages at the end, then everything worked.
This series of commands
make install is a very common pattern for installing software on a *nix like system (such as mac). If you didn’t already know these commands though, not to worry there is a README that tells you to look in the INSTALL file for directions. When in doubt, check for a README file, or other all caps files in the base directory of a library.
Once finished you should have the bison command on your machine
By default the bison binary is placed in
/usr/local/bin which should be in your path. If it isn’t you can add it on to your path in your
Now that we’ve got dependencies on your system it’s time for the main show, we’re going to compile and run mruby!
Go back to the directory where you cloned mruby. I keep all of my code in a
projects directory under documents
Note: Your mruby source will likely be in a different file.
Once in the folder simply run
If everything worked, you should be able to see binaries in the
If you got errors, make sure that bison is available. Try googling for your errors. If everything compiled fine then you can go ahead and run
mirb which is the mruby version of IRB:
If you were able to run
mirb, great job! You just compiled the hottest new ruby implementation and it’s not even released yet!
You also get access to the
mruby command that behaves very similar to cRuby:
If you wanted to have
$ mirb as a command to run anywhere on your computer just like
$ irb you could copy it over to a folder in your PATH:
Or if you didn’t want to copy the file you could make a symlink. This is actually how libraries like RVM allow you to have multiple versions of ruby installed at the same time, it keeps them in separate files and then changes your the simlink or your PATH to point at the propper location depending on which Ruby you want to use.
Now that you’ve got mruby on your computer what can you use it for? Since this implementation can run on micro-controllers and embedded systems and your laptop, you can build programs on your own machine and then port them over to another system. Right now there are no libraries for mruby since it is so young. One of the design decisions is to only support functionality available on all devices. This decision means that there is no native file, process, or thread support since it can’t be assumed that mruby will always run on an OS. If you need those things, there is an active fork of mruby/mruby that adds these features https://github.com/iij/mruby, the install process should be similar.
Typically different programming languages talk to one another by compiling libraries that can be linked to dynamically. So if you wanted to make something really fast in cRuby you could write it as a c-extension. With mruby the process is actually backwards, most people would write their program in C and then embed mruby directly into their program when in areas where they need more flexibility. This is especially useful in game design, or for scripting tests in embedded systems. Anywhere you can run Lua, mruby should fit as well. An example of an existing mruby project is mod_mruby which allows you to run mruby inside of the Apache server similar to mod_lua.
At its heart mruby is a subset of cRuby, so see what things you can port over and get to run. If you were lucky enough to attend Matt Aimonetti‘s talk at AlohaRubyConf you may have seen some mruby generated mandelbrot sets. Now you too can generate some beautiful mandelbrot sets in the comfort of your own home. Quick grab the code:
Then run it:
You might notice it runs faster in mruby than cruby using the
This is due to mruby’s speed in floating point calculations. The mruby implementation isn’t built for speed, but rather size. If it happens to be faster in a few areas, that’s just a happy coincidence. Matt has done some good work with mruby, including his getting started with mruby guide.
Maybe you’re starting to dream of all the microcontrollers, or lego mindstorms you’re going to be hacking with mruby, or maybe you’re just happy you know mruby better. Either way, hopefully you appreciate all the work that goes into compiling and packaging binaries to run on various systems, and how
PATH works. Running mruby locally is just the beginning, it’s up to you to have the vision to build your killer embedded program. Since mruby should be able to run anywhere you’re only limited by your imagination. We can run mruby on any system large or small, wouldn’t it be cool if we could compile it to run on Heroku? Maybe we’ll save that for next week…