This articles was published on 2012-06-02

mruby on mips

Due to the reason that I paused for a moment my activities on improving the testing platform for mruby (the reason is already clarified *happy*) I took a look at some hardware which was available at my place. I found a small embedded device with the following specification:

Atheros SoC AR9331, this means a 400Mhz MIPS CPU, with USB, Ethernet and 802.11n interface. Additionally there is 4MB Flash available on the device:


Porting mruby to this little device consisted of three steps

Setting up cross-compiling toolchain

I’m a huge fan of OpenWRT. Many people know that OpenWRT is an awesome embedded Linux Distribution. But what many people don’t know is, that OpenWRT has an awesome implementation of a Cross Compiling toolchain. They didn’t really invented something by themselves but they build up a nice environment in which you can just cross-compile stuff even if you don’t want to use it on their platform. Writing an OpenWRT specific Makefile is as easy as this:

include $(TOPDIR)/
include $(INCLUDE_DIR)/



include $(INCLUDE_DIR)/

define Package/mruby
  CATEGORY:=Base system
  TITLE:=Embeddable Ruby Language

define Package/mruby/description
  mruby is an embeddable version of the Ruby Programming language.

define Package/mruby/install
  $(INSTALL_DIR) $(1)/usr/sbin
  $(INSTALL_BIN) $(PKG_BUILD_DIR)/bin/mruby $(1)/usr/sbin

$(eval $(call BuildPackage,mruby))

Pre-Compiling mrbc

There is one small trap in the mruby compile process. Parts of mruby are written in Ruby itself. During the compilation process a tool called mrbc will be compiled which then compiles all Ruby files under mrblib. The result is some C-Code which then will be again compiled to the final object. The problem for cross-compiling is now that we need to compile mrbc for the host machine but the result of mrbc has to be compiled for the target machine. Our cmake branch of mruby has already some features to support that but the default Makefiles aren’t able to do that. Due to the reason that I don’t want to mess around with cmake inside of the OpenWRT toolchain I decided to just compile the mrbc static on my machine up-front. Then I deleted everything except the bin/mrbc file. Afterwards I could bootstrap the complete compile. The Makefiles are smart enough to recognize that they don’t need to compile mrbc again. So they just skip that process and they use my host compatible version of mrbc to prepare all Ruby files for the target machine.

Redirecting LL to target gcc

matz is using LL inside of his Makefiles to prepare the final libmruby. I’m not sure if this is very standard conform. Nevertheless my default toolchain doesn’t recognize this abbreviation. So I had to change the Makefile there too.

The Result

As you will see, compiling for MIPS in a proper toolchain and with a little bit of stripping you can bring down the mruby binary to a size of 429K. I bet I can make it even smaller in the future:

mruby binary for MIPS (AR9331 SoC) (ZIP 162K)

root@OpenWrt:~# ls -lah /usr/bin/mruby
-rwxr-xr-x    1 root     root      429.4K Jan  1 00:05 /usr/bin/mruby
root@OpenWrt:~# uname -a
Linux OpenWrt 3.2.5 #3 Wed Feb 15 13:46:20 SGT 2012 mips GNU/Linux
root@OpenWrt:~# cat /proc/cpuinfo
system type		: Atheros AR9330 rev 1
machine			: TP-LINK TL-WR703N v1
processor		: 0
cpu model		: MIPS 24Kc V7.4
BogoMIPS		: 265.42
wait instruction	: yes
microsecond timers	: yes
tlb_entries		: 16
extra interrupt vector	: yes
hardware watchpoint	: yes, count: 4, address/irw mask: [0x0000, 0x0060, 0x03c0, 0x0280]
ASEs implemented	: mips16
shadow register sets	: 1
kscratch registers	: 0
core			: 0
VCED exceptions		: not available
VCEI exceptions		: not available

root@OpenWrt:~# mruby -v
mruby - Embeddable Ruby  Copyright (c) 2010-2012 mruby developers
puts "Hello World"
  local variables:
      method='puts' (276)
        NODE_STR "Hello World" len 11
irep 110 nregs=4 nlocals=2 pools=1 syms=1
001 OP_STRING	R3	'Hello World'
003 OP_SEND	R2	'puts'	1

Hello World