This whole thing started as an effort to get IronRuby on board the rvm train. I started looking around for documentation on how to build/install IronRuby from source with Mono but the blogs and documentation I found where mostly outdated and full of broken links. I guess this is due to the bumpy ride IronRuby has had with owners, repositories and build processes changing several times in a short period of time.
In order to get IronRuby on rvm I needed to figure out how exactly IronRuby builds. At first this seemed like a trivial task however it soon proved to be a bit more complicated.
I want to share my findings with everyone and hopefully I’ll save someone a bit of time. The process I describe below works with IronRuby source tagged “v1.1.2″ and “v1.1.3″. It also works with head, which at the time of writing is revision 8099de3e15b5c28f32fd.
I’ve tried the process on both OSX and Ubuntu and it seems to work fine but please let me know if something breaks down for you.
The basic outline of the build and installation processes is:
- Check Prerequisites
- Get the Source
- Build IronRuby
- Gather Resources
- Create Scripts
- Configure IronRuby
- Hook Everything Up
To build and install IronRuby from source you will need git (obviously) and Mono with C# 4.0 compatibility and developer tools.
If you have Mono 2.10 you should be safe. The Mono binaries you want to make sure are on your system are mono, dmcs and xbuild.
$ mono --version Mono JIT compiler version 2.10.1 (tarball Fri Feb 25 15:56:49 MST 2011) Copyright (C) 2002-2011 Novell, Inc and Contributors. www.mono-project.com TLS: normal SIGSEGV: normal Notification: Thread + polling Architecture: x86 Disabled: none Misc: debugger softdebug LLVM: yes(2.9svn-mono) GC: Included Boehm (with typed GC)
$ dmcs --version Mono C# compiler version 184.108.40.206
$ xbuild /version XBuild Engine Version 220.127.116.11 Mono, Version 18.104.22.168 Copyright (C) Marek Sieradzki 2005-2008, Novell 2008-2011.
Get the Source
After figuring out the authoritative repository for IronRuby this was probably the easiest part. I’ve decided to install my IronRuby into /usr/local/ironruby, where you decide to put it is absolutely up to you.
$ mkdir /usr/local/ironruby $ cd /usr/local/ironruby $ git clone git://github.com/IronLanguages/main.git src $ cd src
If you want to build from a specific tag just checkout that tag
$ git checkout v1.1.3
We will be using xbuild to build IronRuby. This is the equivalent of msbuild on a Windows system. The build itself is simple, it’s only one command and shouldn’t cause you any trouble.
$ xbuild /p:Configuration=Release Solutions/Ruby.sln
It will most likely generate some warnings but those are safely ignored. The binaries should now be built in bin/Release.
Gathering the resources is basically just copying all the files needed for a full installation into the appropriate folders. The two important folders that IronRuby uses are bin, for binaries, and lib, for libraries, simple.
Let’s start with the lib directory since this is the simpler one of the two. The lib directory holds the ruby libraries that are used by IronRuby. This is mostly Ruby 1.9.1 StdLib with some modifications but also some specific IronRuby libraries.
$ mkdir /usr/local/ironruby/lib $ cp -R /usr/local/ironruby/src/Languages/Ruby/StdLib/* /usr/local/ironruby/lib
The bin directory on the other hand requires files from two different places.
$ mkdir /usr/local/ironruby/bin
First, of course, we need the binaries we just built.
$ cp /usr/local/ironruby/src/bin/Release/* /usr/local/ironruby/bin
In addition to those we also need some other script binaries found in the IronRuby source. There are several *.bat files that can safely be skipped since I’m assuming we are building and installing on a *nix system.
cd /usr/local/ironruby/src/Languages/Ruby/Scripts/bin/ cp !(*.bat) /usr/local/ironruby/bin
We are almost done with the bin directory but we still need a couple of scripts that are not included in the repository. These are not really complicated scripts so we can just add them manually.
The scripts I’m referring to are ir, iirb, igem, iri and irdoc. In order to create the first script, ir, we need to know the full path to our mono binary.
$ which mono /usr/bin/mono
Now we can create the script ir in /usr/local/ironruby/bin with the following content
#!/bin/sh exec /usr/bin/mono /usr/local/ironruby/bin/ir.exe $@
The other scripts are all similar so I’ll just list them below.
#!/bin/sh exec /usr/local/ironruby/bin/ir /usr/local/ironruby/bin/irb $@
#!/bin/sh exec /usr/local/ironruby/bin/ir /usr/local/ironruby/bin/gem $@
#!/bin/sh exec /usr/local/ironruby/bin/ir /usr/local/ironruby/bin/ri $@
#!/bin/sh exec /usr/local/ironruby/bin/ir /usr/local/ironruby/bin/rdoc $@
Don’t forget to make your scripts executable.
$ chmod ug+x /usr/local/ironruby/bin/ir $ chmod ug+x /usr/local/ironruby/bin/iirb $ chmod ug+x /usr/local/ironruby/bin/igem $ chmod ug+x /usr/local/ironruby/bin/iri $ chmod ug+x /usr/local/ironruby/bin/irdoc
IronRuby is a .NET/Mono application and as such has a wonderful *.config file. Fortunately we don’t need to do a lot of configuration we only need to set the relative path to the lib directory. The config file is found in /usr/local/ironruby/bin/ir.exe.config
Locate the following line and change the value to your relative librarie path, “..lib” if you have been following along.
<set language="Ruby" option="StandardLibrary" value="..lib"/>
Hook Everything Up
You should now have a built and working install of IronRuby. The only part missing is to add your install path to your system path.
$ export PATH="/usr/local/ironruby/bin:$PATH"
Well this process is tedious, manual and frankly quite hurty. I will continue my dialog with Wayne Seguin of rvm and if all goes well we might get IronRuby with mono on rvm.
Unfortunately I have very limited time in which I can work on these things. If anyone wants to help with IronRuby on rvm please ping me. I would especially like to hear from anyone already working on Mono or IronRuby.
Those of you who know me know that I’m a big Ruby fan. I’ve been doing as much Ruby as I can squeeze in for the past 6 years, which hasn’t been that much since I usually get paid for doing .NET (C# / VB.NET).
Given this you might think I would jump on IronRuby since it mixes my passion for Ruby with my day-to-day work of developing on the .NET platform. However I haven’t really explored IronRuby simply because I didn’t see any benefits over using standard Ruby. I’m not saying there aren’t any benefits I’m just saying that there where none for me.
Lately however I’ve been going deeper and deeper into the rabbit hole of programming languages. I’ve started looking at things like language semantics and complier design. I’ve played around with several different well-known and obscure languages and I’ve started going down on the lower levels of framework internals.
From this point of view back-ends become extremely interesting. What does your compiler emit – Machine code, Java bytecode, MSIL?
I have great respect for both Java bytecode and MSIL and think that virtual platforms are the way to go, I mean who needs machine code year 2011 anyway, right?
When given a choice between the JVM and CLR I find the CLR much more pleasant to work with. Maybe it’s because of my history with .NET that I find the CLR fits me better than the JVM.
With all this in mind I have finally found a really awesome use for IronRuby, emitting IL! Sure this could be done in C# or VB.NET but for the heck of it and just because I prefer to work in Ruby I did it in IronRuby.
I leave you with a final example of how to do Hello World in IronRuby the macho way. This code emits Hello World IL and creates a HelloWorld.exe that executes on .NET/Mono.
require 'mscorlib' # Aliases for some of the .NET types we will use AssemblyName = System::Reflection::AssemblyName CurrentDomain = System::AppDomain.CurrentDomain AssemblyBuilderAccess = System::Reflection::Emit::AssemblyBuilderAccess TypeAttributes = System::Reflection::TypeAttributes MethodAttributes = System::Reflection::MethodAttributes OpCodes = System::Reflection::Emit::OpCodes BindingFlags = System::Reflection::BindingFlags # Define assembly, type and main method. This is required by all programs assembly_name = AssemblyName.new("HelloWorld") assembly = CurrentDomain.DefineDynamicAssembly(assembly_name, AssemblyBuilderAccess.RunAndSave) assembly_module = assembly.DefineDynamicModule("HelloWorld.exe".to_clr_string, "HelloWorld.exe".to_clr_string) program_type = assembly_module.DefineType("Program", TypeAttributes.Class) main_method = program_type.DefineMethod("Main", MethodAttributes.Public | MethodAttributes.Static) # Get the il generator for the main method il_gen = main_method.GetILGenerator # Emit hello world to the main method il_gen.Emit(OpCodes.Ldstr, "Hello world!") write_line_params = System::Array.of(System::Type).new([System::String.to_clr_type]) console_type = System::Console.to_clr_type write_line_method = console_type.GetMethod("WriteLine", BindingFlags.Public | BindingFlags.Static, nil, write_line_params, nil) il_gen.Emit(OpCodes.Call, write_line_method) il_gen.Emit(OpCodes.Ret) # Create the program and save it to disk program_type.CreateType() assembly.SetEntryPoint(main_method) assembly.Save("HelloWorld.exe")
This post started as a reply to “CEO Friday: Why we don’t hire .NET programmers” by David over on the Expensify blog but it got so large that I decided to turn it into a blog post instead.
I work at tretton37, we work mostly on the .NET platform and sells .NET and Agile expertise to clients that value skill, personally I really don’t care if someone has .NET on their resume or not, it doesn’t tell me anything about who they are as a developer.
David made several statements that I don’t agree with and I’ll try to give my opinion on these things. I won’t go in to the whole language/platform rant since it seems to have been discussed over and over again and David has clarified this “typo”. But I will add to the discussion that .NET is a platform developed by Microsoft however it is in itself larger than Microsoft. Not admitting this is an insult to the Mono, MonoTouch and MonoDriod people and many more.
That said, I think that David is focusing too much on the language/platform. Great developers come in all shapes and sizes and to these people tooling (language/platform/IDE) does not matter. They are professional enough to look at a problem and suggest a solution using the most efficient tool. Most of them know several languages and platforms and would not choose a sub-standard tool.
I myself am proficient in several languages and platforms including Ruby and C++. While I love the speed Ruby on Rails gives me in development I am (mostly) constricted to database driven web apps. If you try to do anything else, well that won’t work for you. ASP.NET MVC takes a bit more time to get started and development is a bit slower but on the other hand I would say it is more flexible albeit constricted to the MS platform. I guess what I’m trying to say is that every platform/framework has pros and cons and there is no black and white.
Also platform matters in post development, even if the .NET version took longer time to develop. Ubuntu + Nginx + Phusion Passenger has caused me a lot more grief than Windows + IIS. I’m sorry to say it and I wish it wasn’t true but it is.
I have almost 10 years of professional experience and 8 of those where spent doing .NET (2 years C++). Dump me in the wilderness with a Swiss army knife and I’ll cook you up a squirrel, hell I know MIPS assembly! But given an out-in-the-wilderness scenario my first choice probably would not be .NET.
Why choose .NET? .NET is a rather flexible and productive platform that solves certain problems in certain eco systems very well, not choosing .NET in these cases would be unprofessional.
Is it good for start-ups? I really don’t know. My theory is that one problem for start-ups might be that they can’t afford it. You need Windows, Visual Studio, Windows Server, SQL Server, etc. All that costs money, money you could be spending elsewhere. Ubuntu, Vim, Nginx, Passenger, etc are free. Even with BizSpark and WebSpark choosing an MS stack is still more expensive in terms of how efficiently you use your hardware (Yes! The same hardware will be able to serve much more PHP driven pages on Apache than .NET pages on IIS).
So measuring idea to cash value stream, which one is more efficient for you? What choice will save you money in the end?
If you only take away one thing from this it’s that the tools don’t make the developer. It’s a completely different set of skills and if you can’t learn new tools in a jiffy then you’re not good enough yet. If you had bad experience with hiring developers that have .NET on their resume and getting them on board with another technology you probably have a too lax hiring process that doesn’t check for the right skill set.
Shameless plug: We at tretton37 are also hiring! We are looking for more skilled .NET professionals that like having fun. Read more about how it is to work with us. Ping me or apply directly to firstname.lastname@example.org.