Monday, May 26, 2014

Nerd Food: Using Mono In Anger - Part II

Nerd Food: Using Mono In Anger - Part II

In which we setup our working environment.

On Part I we explored the reasons why I decided to use Mono in anger. In this part we shall get ourselves a working environment comparable a Visual Studio 2013 setup.

First things first:

  • whilst this post presumes that you may not know everything about Linux, it does expect a minimum familiarity with the terminals, desktop, etc.
  • having said that, we try to keep things simple. For instance note that commands that start with # need to be executed as root and commands that start with $ should be executed as an unprivileged user. Also \ means the command should really be one big line.
  • my distribution of choice is up-to-date Debian Testing, which is where all the commands have been tested; hopefully most things will work out of the box for you - especially if you are using Debian or Ubuntu - but its better if you understand what the command is trying to achieve, just in case it doesn't quite work.
  • Finally, I presume you know about .Net and its libraries - although I do try to give some minimal context.

Without further ado, lets set our Mono environment.

Installing Mono

We start off by following the instructions on installing mono for Debian available in the Mono project wiki:

# apt-get install mono-complete

It's worth mentioning that whilst the Mono page above mentions v2.10.8.1 for Debian Testing, v3.0.6 has actually already been migrated from Unstable so that is what you will be getting. A note on versions here: with Mono, latest is always greatest. The project moves at such a fast pace that getting an old version is almost always a bad idea.

If everything has gone as expected, you should now see something along the lines of:

$ mono --version
Mono JIT compiler version 3.0.6 (Debian 3.0.6+dfsg2-12)
Copyright (C) 2002-2012 Novell, Inc, Xamarin Inc and Contributors.
    TLS:           __thread
    SIGSEGV:       altstack
    Notifications: epoll
    Architecture:  amd64
    Disabled:      none
    Misc:          softdebug
    LLVM:          supported, not enabled.
    GC:            Included Boehm (with typed GC and Parallel Mark)

To make sure we have a fully working setup, lets compile a simple hello world:

$ echo 'class Program { static void Main() { System.Console.WriteLine("HelloWorld!"); }}' > hello.cs
$ mcs hello.cs
$ ./hello.exe

Installing MonoDevelop

Of course, no self-respecting Windows .Net developer will code from the command line; they will ask for an IDE. The IDE of choice for Mono is MonoDevelop - sometimes called Xamarin Studio because they are the main company behind it, and have a commercial product based on it.

It's pretty straightforward to install it on Debian:

# apt-get install monodevelop monodevelop-nunit monodevelop-versioncontrol \
     monodevelop-database monodevelop-debugger-gdb \
     libicsharpcode-nrefactory-cecil5.0-cil \
     libicsharpcode-nrefactory-cil-dev \
     libicsharpcode-nrefactory-csharp5.0-cil \
     libicsharpcode-nrefactory-ikvm5.0-cil \
     libicsharpcode-nrefactory-xml5.0-cil \

You will most likely get MonoDevelop v4.0. Alas, v4.2 has already been released but not yet hit Debian. As with Mono, latest is always greatest. Note that I went a bit overboard here and install a lot of stuff - you may just want to install monodevelop. I added the NUnit integration and the Version Control integration as well as the refactoring tools.

Once its installed you can start it from the main menu. It should look vaguely like this:

MonoDevelop's main window

The very next thing we need to do is to install the NuGet add-in for MonoDevelop. To do this:

  • Go the Tools menu, Add-in Manager;
  • Click on the Gallery tab;
  • Click on the Repository combo-box and select Manage Repositories…;
  • Click on the Add button and select Register an on-line Repository
  • Paste the repository from the page above, e.g.: and click Ok.

MonoDevelop Add-in Repository

You should now be able to find the NuGet add-in by searching for it on the search box at the top of the dialog:

Installing NuGet Add-in

In my case its already installed - in your case you should get an Install option. Unfortunately we're not out of the woods just yet. We need to setup the certificates to allow us to download packages:

# mozroots --import --sync
# certmgr -ssl -m
# certmgr -ssl -m
# certmgr -ssl -m

Now, to be perfectly honest there are still some setup issues for NuGet that I don't quite understand, but we'll leave that for later.

Setting up a Solution

To create a solution go to the File menu, New and choose Solution…:

Creating a new solution

This will create a solution with a project. Now, on the main screen create a second project, say MyProject.Tests, by right-clicking the solution, click on Add then Add New Project… and then fill in the project details: NUnit project and the name.

Adding a new NUnit project

To be perfectly frank, as with Visual Studio, I tend to create projects and solutions from the UI and then edit the raw .sln and .csproj files to get them in my preferred directory layout. At any rate, for this really simple solution we just get the following:

The HelloWorld solution

Now go to both project options by right-clicking on the project and then Options and find General. There update the target framework to Mono .Net 4.5.

Using .Net 4.5

You will get some blurb about project file changes, just accept it. The other thing to do is to use xbuild, Mono's equivalent of msbuild to do the building. To do so go to Edit, Preferences and Build. Then tick the xbuild check box:

Using xbuild

Now all we need is to setup all of the required NuGet packages. This is where things become a bit complicated. As I said previously, we set up all the required certificates so things should just work. In practice we still get a few issues. To see what I mean, right-click on a project's references, then Manage NuGet Packages…. The following message comes up:

NuGet certificate problem

If you click yes, you should then get the full blown list of NuGet packages. But it's a bit annoying to have to do that since apparently we have installed all of the required certificates. Also, as we shall see, the NuGet restore fails due to certificate problems but we'll leave that one for later. Once you waited for a bit, the packages screen will come up, and you can use the search box to search for packages and once happy, click on Add:

Adding Log4Net in NuGet

Using this workflow, add all the required packages. For example, in my case I added:

  • Main project: Log4net, Castle Core, Castle Windsor, Mongo CSharpDriver, Newtonsoft.Json
  • Test project: NUnit. I removed the reference that Mono added and forced it to go via NuGet. This saves you from a lot of problems related to incorrect NUnit versions.

A few points to note here. NuGet works but it's a little rough around the edges. When you are using it in anger, the following things will become annoying:

  • the whole certificate thing, which seems to make the initial NuGet window slower. Fortunately this appears to happen only once for a running session.
  • the inability to use NuGet restore is a pain; it means every time you swap machines you need to faff around to re-download packages. I use a dummy project for this - e.g. add packages to a project that does not have them and then remove them.
  • the NuGet add-in ignores the .nuget configuration; instead uses a "hard-coded" package directory at the same level of the solution. This is a bit painful because your Windows developers will see the packages in one location (i.e. where the .nuget config states it should be) but it will be elsewhere in Mono. Best not to use these until they are supported in Mono.
  • NuGet add-in doesn't seem to work when there is no network connection. This is a bit painful because it means that you can't add a dependency to a project that had already been added to another project without being online. In this scenario the easiest thing to do is to edit the .csproj and packages.config files manually.

A Note on F#

As I spent a considerable time describing the F# setup in the past (Adventures in F# Land Part 1, Part 2 and Part 3), it's only fair we cover how things are done these days. First install the required packages:

# apt-get install fsharp libfsharp-core4.3-cil libfsharp-data-typeproviders4.3-cil

Again, YMMV - I always go a bit overboard and install everything. Then in MonoDevelop install the Add-in. To do so simply go to Tools, Add-in Manager then click on Gallery and expand Language Bindings. Click on F# and then install.

Adding F# Support

It is that easy these days. We may have to do a F# in anger series later on, to see how well it stacks up.

Setup Review

First I'd like to say that there are a lot of positives in the setup experience. For example, I just spent the best part of two days getting Visual Studio to work due to some licensing issues - it just wouldn't accept my key for some reason. Also Visual Studio 2013 is rather demanding hardware wise, whereas MonoDevelop seems to hover on the 200 MB range (my actual solution has around 12 projects).

And on the main, the polish on MonoDevelop is quite good, with many things just working out of the box as they do in Visual Studio. And, once you get past some of it's minor quirks, Matt Ward's NuGet Add-In does work; I have been using it in anger for 3 weeks and I can attest to that. But it could be argued that NuGet is such a central component in the .Net experience that it should warrant thorough QA - perhaps by Xamarin - to try to bullet-proof it, at least for the hot use cases.

On the main, we're still very happy campers.

Date: 2014-05-26 20:12:12 BST

Org version 7.8.02 with Emacs version 23

Validate XHTML 1.0


Brendan Ingram said...

Good stuff. I just spent the weekend migrating our FunkyCMS platform off VS2012 onto Mono (Debian 7). I'll be putting a blog post up on my personal blog ( soon if you're interested. Actually, Saturday was spent migrating from MSSQL2012 to PostgreSQL 9.4 and Sunday spent on Mono, so all in all, I'd say that's pretty good progress, considering it takes 2 days just to (re)install Windows 7 and all the relevant apps!

The main difference to what you've done is that I didn't install using the packages, I built everything from source. In the overall scheme of things it was pretty painless, but there were a few quirks (as is expected building from source). If you haven't done it already, give it a go. MonoDevelop 5.1 (current version in Git master) is pretty cool, and of course, as you say, the latest version of Mono in particular is better.

Next stop for me - getting some ASP.NET vNext code happening in Mono.

Marco Craveiro said...

Very interesting Brendan - really looking forward to your post! I tried building MonoDevelop from master but hit a problem with the mono-addin. Did you use mono-addin from master?

Marco Craveiro said...

Brendan, good post on vNext here:

Will use these instructions to set myself up methinks...

Brendan Ingram said...

Thanks for the follow-up link Marco. I had seen that one, and it's a really good guide. Most recently I also got stuck building MonoDevelop from master. It seems that when I did build it a few weeks ago that the state of the Git repository was better than it is now.

I actually changed from Debian to Xubuntu so that I could use the MonoDevelop package, as the Ubuntu package was newer than the Debian Wheezy package. Long story short, for our product there are too many hurdles and distractions to move completely to Linux/Mono now. As such, we're going to stay with Visual Studio for the time being.

I'll be keeping a close on ASP.NET vNext though, as I think there are some extremely exciting things coming there :)

Marco Craveiro said...

Hi Brendan,

Yes, the packaging is a pain in the proverbial really. I did manage to find something that worked for me in the end but the great news is that Xamarin will be improving Linux support! See part IV

Also keeping a keen eye on vNext, hopefully I'll get to play with it in the next few months!