Builds, Installers and Frustration
A.K.A Why I Love Documentation
I recently put together a small tool to help diagnose errors in the configuration (i.e. ccnet.config). After getting some good feedback it on it, I decided it would be nice to add to the trunk, and even nicer if it ended up in the final installer (since this is what most people will use).
Like a lot of areas in CC.Net, there is no documentation on developing for the installer. But given that installers are reasonably simple, I thought I’d give it a try. And that is where my frustration began!
I should add as a side note, I’m a keen user of WiX. This is a set of open-source tools that take in an XML file and generate an installer out the other end. It is very simple to use (although I do have some problems with it) and has a great price tag – free!
CC.Net uses NSIS instead, which is more of a scripting tool for building installers. It is also free, but I find it a little harder to read and understand (of course I’m probably just used to WiX and find it hard to convert).
Anyway, back on topic, this post is about what I have learnt to get a new project included in the installer.
Where I Started
Now, since I knew that CC.Net uses NSIS I thought all the information for the installer would be in ccnet.nsi (this is the script file for the server). I was wrong
The file has all the instructions for installing the product, and nothing about the files to be included. I knew the names of the files currently included, but nowhere did I find these in the script file.
Thus I was lost!
First Things First: The Build
As we start out with code, not binaries, the first step is to generate the executables. CC.Net already has a pretty good build file that uses NAnt. This does all sorts of wonderful things, including compilation, unit tests, code coverage and most importantly for me – it generates the installer.
Again, it doesn’t have any lists of file, but it has three important pieces of information:
- First, it has what is actually built and what parameters are passed in
- Next it has when the installer is generated, and the build steps that must happen first
- Finally it has a build step for generating a deploy folder
I’m going to shuffle the order of these around a little because I didn’t discover them in this order.
Instead, the first piece I found out was the order of build steps. The build step (or target) that generates all the installer is called “dist”. This depends on the deploy targets for CCTray, server and dashboard (there’s an intermediary target in between called “deploy”).
Now while “dist” is the actual build step that generates the installer, it needs all the files copied to a deploy folder first. This turns out to be critical because the .nsi file refers to this folder and builds the installer using the files in this folder!
Thus to include new files in the installer all I needed to do was modify the build step for generating the deploy folder (see important piece of information #3).
Where Do You Think You’re Coming From?
Looking at the existing executables I saw they came from the build folder, and where slightly re-arranged to be in the correct locations (plus there were some exclusions). However, when the executables for the validator went into another folder – the standard binrelease folder from C#.
Again I searched and searched through the build script to find the step that copies them – but I couldn’t find it anywhere. Which brings me to important piece of information #1 – the parameters that go into the compilation.
It turns out that CC.Net projects have an extra build configuration called “Build”. This is very similar to the standard “Debug” and “Release” builds, but (and this is a big but) it sends the outputs of the build to a folder underneath the global build folder!
Once I had figured out these important key points, everything else fell into place!
A Recipe for New Projects
So, here are the steps for adding a new project so it is included in the installer:
- Add a new build target to the project called “Build”.
- Configure this project so it outputs the binaries to a folder underneath the global build folder.
- Add some lines to the NAnt build script to copy the binaries into the correct location within the deploy folder.
And that’s it! It took me almost three hours to figure out these three steps
Addendum: Adding a Shortcut
It is also very easy to add a shortcut. This is covered in the NSIS documentation, so it didn’t take me long to figure it out.
In the .nsi script file there are a number of “Section” entries. There are three main sections:
- CruiseControl.NET Server (SEC01)
- Web Dashboard (SEC02)
- Examples (SEC04)
Each of these sections map to an option the user can choose. In these sections are the commands for installing the product, including creating short cuts.
So, to add a new shortcut, select the correct section and add a CreateShortCut command with the correct parameters (location and target).
Even simpler than adding files to the installer