Friday, March 27, 2009

Getting Started with Rake on .NET Projects

I attended Developer Day in Durham last weekend, and had a blast.  The event was very much Ruby-centric, which is a little out of my comfort zone.  However, there were plenty of things that I’m bringing back to my day job on .NET and Java projects.


The first two things I resolved myself to do:  1)write less XML, and 2) try to incorporate scripting languages (starting with Ruby) into my routine tasks.  This led me to Rake.  Rake helps me accomplish both goals at one time.  I get to stop writing XML for my build scripts, and use Ruby to build my projects.


There are a lot of blog posts on Rake and even some on Rake with .NET.  However, I didn’t find one that got me running build scripts in Rake from scratch.  I’m focused on the simplest case for .NET.  If you want more general Rake information, go to Martin Fowler’s article.  If you want a more complete (and very entertaining) tutorial, check out the Rails Envy site.

So here it goes…


1. Get Ruby

I’m on a windows machine, so I used the One Click Installer.  I ran the installer, re-booted my machine, and was good to go with Ruby (Rake is delivered as part of the Ruby install).


2. Find a Project that Needs Building

I set up a very simple solution that has two class libraries (DoStuffInDotNet and TestStuffInDotNet).  One has a single class with limited functionality.  The other has a single NUnit test.  I have also included a tools folder, which contains the NUnit test framework.


SolutionImage


3.  Create a Rake File

I created a file called rakefile.rb.  I’ll break down each part of the file below.

The first line sets up the default task.  In this case, it is calling the build task.  So, from this folder, “build” executes by simply typing in “rake”.

task :default => :build


The next line shows that “build” is  a composite task that is comprised of the “clean”, “compile”, and “test” tasks.



task :build => [:clean, :compile, :test]


The “clean” task is just calling Ruby’s FileUtils class to remove the contents of the “build” folder.



task :clean do
FileUtils.rm_rf(
"build")
end


The “compile” task calls MSBuild to execute on the solution under the AutomatedDebug configuration.  AutomatedDebug is a setting I created in Visual Studio’s Configuration Manager.  The only difference between this and the default Debug configuration is that my output path is set to “..\..\build\Debug\”.  This will put the output of the rake build into the “DoStuffInDotNet\build” folder.



task :compile do
params = '/t:Rebuild /nologo /v:m /p:Configuration=AutomatedDebug src\DoStuffInDotNet.sln'
msbuid
= 'C:\\WINDOWS\\Microsoft.NET\\Framework\\v3.5\\MSBuild.exe'
sh
"#{msbuid} #{params}"
end


The final task is “test”.  Rake uses the current execution directory as its working directory, so I am using FileUtils to change the working directory to the “build\Debug” folder.  Then I execute NUnit against the test dll.



task :test do
FileUtils.cd
'build\\Debug'
exec
"..\\..\\tools\\nunit\\nunit-console.exe TestStuffInDotNet.dll"
end


From the cmd window, you can just run the command “rake” from the directory that contains rakefile.rb.



image



In effort of completeness, below is the full code in rakefile.rb.  Like I’ve stated early, this is a stupidly simple example.  However, I hope that it can help you get started if you are looking to start from ground zero.



task :default => :build

task :build
=> [:clean, :compile, :test]

task :clean
do
FileUtils.rm_rf(
"build")
end

task :compile
do
params = '/t:Rebuild /nologo /v:m /p:Configuration=AutomatedDebug src\DoStuffInDotNet.sln'
msbuid
= 'C:\\WINDOWS\\Microsoft.NET\\Framework\\v3.5\\MSBuild.exe'
sh
"#{msbuid} #{params}"
end

task :test
do
FileUtils.cd
'build\\Debug'
exec
"..\\..\\tools\\nunit\\nunit-console.exe TestStuffInDotNet.dll"
end

Thursday, March 12, 2009

How to make your code last: call it a temporary solution

Throughout my career, I have found several common themes that appear over and over again.  One of them popped up again recently: If you say you are going to develop a temporary solution and clean it up later, you never will.  It’s not always a matter of laziness (although, at times, it is), the odds are very high that an obstacle will get in our way later.

I was writing a demo Web Part project last week in order to demonstrate how SharePoint projects can use Continuous Integration.  The project itself was not the focus of the talk, I just wanted to demonstrate how CI works. 

Although the content of the solution was not significant to my original theme, it caught my audience’s attention.  Once we got through the discussion of CI, they were very interested in the approach I took and how I was deploying the Web Parts.  It turns out that they were having problems building and deploying Web Parts themselves.

Fortunately, I learned my lesson long ago that all code I demo or commit to source control should be thought out.  I could have cut a lot of corners when building this project, but I didn’t.  I’m not saying that I write perfect, bug-free software, I just attempt to do a good job as a professional. To quote the Manifesto for Software Craftsmanship I’ve come to value “Not only working software, but also well-crafted software.”

When the presentation was over, the client wanted my code and build scripts.  They are still interested in CI, but my sample code and build scripts solved the exact problems they were having at that time.  Now this is a lucky situation where my little demo app solved a problem for a client that I didn’t know they had.  But think if I had taken short cuts or allowed myself to get sloppy.  I would have had to spend the next day or week rewriting the project before I handed it over to them.  Or I would have lost credibility with them because my code could have been short cutting around their problem.

In the end, my code and/or its build script may be the building blocks for the client’s own Web Parts and projects.  So this seemingly inconsequential application may become the foundation for future code.  They may not use the code itself in the future, but there is power there because it helps form the clients initial understanding of Web Part development.  How about that?  If I had done a sloppy job, that means their initial understanding would be … well… sloppy, or even worse, incorrect.