Hack the Build: Use Whidbey Beta2 to target .NET Runtime 1.1

Jomo Fisher – A while back, I posted a sample that showed how to target the .NET 1.1 runtime (the version that came with Visual Studio .NET 2003 also known as Everett) with MSBuild. Now Beta 2 has rolled around and I can see that there have been enough changes to MSBuild to warrant an entire rewrite of that original sample.

I’ll get into the details of how it all works down below, but right now let’s just get it working on your machine. Here are the steps:

(1) Copy this MSBuild targets file to “C:\program files\msbuild\CrossCompile.CSharp.targets”

(2) Create a new C# project somewhere called MyApp.

(3) Use notepad to edit MyApp.csproj. Replace the entire <Import> tag with

  <Import Project="$(MSBuildExtensionsPath)\CrossCompile.CSharp.targets" />

(4) When prompted, reload the project. You’ll have to answer a security dialog.

(5) In VS, click the drop-down that says ‘Any CPU’ and select ‘Configuration Manager’

(6) Under Active Solution Platform, select <New…>

(7) Select ‘.NET 1.1’ (pretty cool, eh?) and press OK.

(8) Build and notice error about System.Collections.Generic. This means its working because generics aren’t supported in 1.1.

(9) Open Program.cs and delete the line:

using System.Collections.Generic;

     And rebuild.

That’s it, its working.

As with the last sample I posted on this, I expect that only basic scenarios will work here. If you run into a problem, drop me a note. If I see a quick solution I'll post it. Otherwise, I can still publish those limitations here so that other people can learn from your experience.

What’s New?

There are some differences between this version and the prior sample I published that show off some nice new features in MSBuild for Beta2:

  • This version shows how to add entirely new Platforms for VS to pick up. See the $(AvailablePlatforms) property in CrossCompile.CSharp.Targets. You could, pretty easily, add other targets from .NET 1.0 or any other tool that is roughly command-line interchangeable with CSC.EXE.
  • The reference resolution logic in this version is far more robust. Many more scenarios should work now, including references to third-party assemblies as well as project-to-project references. (Though you still can't reference 2.0-compiled assemblies into 1.1 projects--this is a limitation built into the CLR itself).
  • We’ve added a new built in property called $(MSBuildExtensionsPath) which is defined to be like “C:\Program Files\MSBuild”. This is a well-known spot where people can dump their custom targets files. This saves you from having to hard-code a path in your project or template.
  • Targets can now be entirely overridden. The GetFrameworkPaths targets from Microsoft.Common.Targets is overridden in CrossCompile.CSharp.Targets so that an alternate directory for target framework directory can be injected.
  • This version doesn’t build 2.0 and 1.1 at the same time. This is nicer, I think, because otherwise you see duplicate errors when you build.

Moving On

At the end of this month I'm moving from the MSBuild team (5th floor, building 41 in Redmond) to the C# team (1st floor, building 41 in Redmond). Working on MSBuild has been a blast and I intend to keep on blogging about it if I think I having something of value to say. After a while, I hope to have something useful to say about C# too. I think "Hack the Build" still fits, so I'll keep the name.

This posting is provided "AS IS" with no warranties, and confers no rights.