MSBuild -- Use the .csproj file or roll your own?

jerhinesmith picture jerhinesmith · Oct 20, 2008 · Viewed 13.3k times · Source

OK, so I readily concede that I'm a newbie when it comes to continuous integration.

That being said, I'm trying to set up a CC.NET environment to educate myself, but I'm having trouble finding the information I need to get the automated build portion set up.

As I understand it, in C# the .csproj file produced by VS 2005 and forward is a valid MSBuild file. To wit, I've been able to integrate the MSBuild task into CC.NET using the .csproj file, but I have a few issues with this:

  1. There's a lot going on in here that I'm not sure I really need in an automated build environment.
  2. I didn't create this file. I do not understand it, and that scares me. (Programming By Coincidence)
  3. Most of what is going on seems to be abstracted through $(MSBuildToolsPath)\Microsoft.CSharp.targets
  4. As a result of 1, 2, and 3, modifying the file to include something like MbUnit seems convoluted and more difficult than it needs to be. My only real option is to include it in the AfterBuild section, which seems kind of like a hack to me.

So, a few questions for the CC.NET folks, the MSBuild folks, and the MbUnit folks.

  1. When using MSBuild, is it advisable to use the VS-generated .csproj file as the build file? Or should I create my own?
  2. Should MbUnit tests be part of the MSBuild file or the CC.NET file? My research seems to suggest that they belong in the MSBuild file. If that is the case, do I create a new MSBuild .proj file and check that in to CVS in addition to the .csproj file? Or does the MbUnit task become part of my .csproj file?
  3. Similar to question 2. If I add the MbUnit tests to the MSBuild file and end up using the .csproj file, is the Target Name="AfterBuild" really the section to add that information? Shouldn't there be a Target Name="Test" section? Using the VS generated .csproj file seems to prevent the second option.

I know there's a lot there, but most of what I've been able to find online assumes a certain level of familiarity with these topics that I just don't have -- unless I'm mistaken, the learning curve for this stuff isn't a curve at all, it's a step function. :)

Edit 1: I updated the text to be a bit more concise and to address some lingering questions I've had with the answers.

Answer

Rob Hunter picture Rob Hunter · Oct 21, 2008

I would recommend using the generated .csproj files - in fact for production, I think using the generated .sln files is a good idea. I have found that you will you gain by using the same solution files as the developers.

Be aware that .sln files are not actually valid msbuild project files - they are transformed into msbuild projects by msbuild itself when they are used as inputs. Tricky!

For learning purposes, you may want to log the build of a .csproj and step through to get an idea of what is going on. MSBuild is a bit more declarative than nant though, so take your time and experiment a bit.

Finally, I would wrap your .sln or .csproj files in a continuous build script project with msbuild tasks to build your projects and run your unit tests together. This way the developers don't have to run the unit test every time they build - but every time they integrate their code the unit tests will run. And yes, make sure they run fast! Anything that takes more than a second should be run during a scheduled (nightly?) build instead. Likely they are less unit tests and more integration tests written with a unit test framework if they take more than a second.

Edit: Some addition information I have found that I have found useful - using MSBuild 3.5 will allow you to get the target output from a .sln file, while this information is not returned in MSBuild 2.0 (though I think it should work for .csproj files in both versions). You can use the output (your built files) as inputs to your unit testing framework.