Yesterday I spent a great deal of time getting my build script for my TwitterNET project to run successfully under Linux on Mono. My build script was already worked nicely on Windows but since I’ve moved to Linux and didn’t really have a Windows computer sitting around I needed to make it work for Linux. The good news here is that NAnt gives us the ability to build stuff against the Mono runtime and find out what operating system we’re running on.
The first thing we need to do is to find out what operating system the build script is running on. We also need to set that to a property so that we can run tests against it later in the script.
[xml]<property name="build.os" value="${operating-system::get-platform(
environment::get-operating-system())}" />[/xml]
As you can see, we create a property called ‘build.os’ which contains the PlatformID of the operating system we’re running the build script on. With that in mind, we need to also create a new property for our folder/file separator, because Linux uses the forward slash (/) while Windows uses the backward slash (\).
[xml]<property name="file.sep" value="" />
<if test="${build.os == ‘Unix’}" >
<property name="file.sep" value="/" />
</if>[/xml]
Pay attention to the if statement in the above code sample, the test part contains a reference to our ‘build.os’ property we defined earlier. We default the slash to the backward slash (backslash), and then if we’re running on Linux (the PlatformID refers to Unix when running on Linux), change the ‘file.sep’ property the forward slash.
So how do we tell it do something that’s for a Windows build only? Well, we just modify the test part of the if task slightly with:
[xml]<if test="${build.os != ‘Unix’}"> <!– Build on Windows –>[/xml]
We’re just changing the ‘==’ to ‘!=’ (which means “not equals”). So now you can go through a build script, and put anything that is Windows specific under the appropriate IF tests, and do the same with the Linux specific stuff.
If you want to look at my build script to see how I handled things, please feel free to look at it, you can find a copy over on the TwitterNet GitHub page.
There are a couple of gotchas though when doing builds on Linux with Mono. The first is that there is no msbuild equivalent in Mono. There is xbuild, but I was unable to get it to work, I think this was because my solution and csproj files are from Visual Studio 2008. What this means for you the user is that you have to make a direct call to the mono compiler (usually ‘gmcs’ on Ubuntu) and pass the references and each individual file. So anytime you add a file to the project, you have to manually add it to the Linux part of the build script.
Another gotcha is the fact that things like NUnit need to be run using Mono, so you have to have different ‘exec’ tasks to handle the differences. This also means you’ll have to make the ‘mono’ command the program that gets run in your ‘exec’ task and the name of the program being run will become a command line argument. This does however work nicely, once you have it configured correctly. I advise looking at my build script to see what I did to make it work.