If you've tried to compile for .NET 4.0 using MSBuild on the command line without having the Windows SDK or Visual Studio 2010 installed, you'll probably have noticed this warning message:
warning MSB3644: The reference assemblies for framework ".NETFramework,Version=v4.0" were not found. To resolve this, install the SDK or Targeting Pack for this framework version or retarget your application to a version of the framework for which you have the SDK or Targeting Pack installed. Note that assemblies will be resolved from the Global Assembly Cache (GAC) and will be used in place of reference assemblies. Therefore your assembly may not be correctly targeted for the framework you intend.
Additionally, if the target platform of your project is set to AnyCPU, MSBuild will copy several files from the .NET Framework into your output directory:
This happens even if your project doesn't reference any of the named .dlls.
So what are these "reference assemblies", are why are they needed for compilation? First, let's look back at .NET 2.0 (which didn't have reference assemblies) so that we can understand the problem that Microsoft wanted to solve.
In .NET 2.0, MSBuild tells the compilers to directly reference the assemblies from the Framework's directory. The problem was: when .NET 2.0 SP1 added new classes and members, developers could accidentally use the new classes and make their program incompatible with the unpatched .NET 2.0.
In .NET 4.0, Microsoft solves this problem by separating the assemblies used for compilation from the assemblies used for runtime. When you install the .NET Framework, you only get the runtime assemblies (installed in the GAC). These may be patched by hotfixes or service packs. However, the patches will not touch the separately installed reference assemblies: the compiler will continue to check your code against the original .NET 4.0 API. In fact, if you try to open the reference assemblies in Reflector, you won't see any code: these assemblies have only the metadata and do not contain any IL instructions. They are intended as a API reference only.
But, while reference assemblies certainly are a good idea, not everybody has them installed. The ".NET 4.0 Targeting Pack" is not available as a standalone download, the only way to get it is to install the Windows SDK 7.1 (a 585 MB download) or to install Visual Studio 2010. So we decided that SharpDevelop 4.0 should be usable without having the reference assemblies installed. You won't get their benefits (when the .NET runtime gets patched), but you should be able to work as you could with .NET 2.0.
So what did we do? First, I implemented a workaround for the "copy local" bug. I don't know why that bug occurs only when targeting AnyCPU, but I understand why this depends on the reference assemblies: MSBuild uses a file called "RedistList\FrameworkList.xml" to decide which references should, by default, be copied into the application directory, and which are part of the .NET framework and thus always present in the GAC. This file is part of the reference assemblies, so MSBuild must be using something else when those aren't installed. The workaround in SharpDevelop adds a custom MSBuild task to the assembly resolution target, which sets CopyLocal=false for all .NET assemblies (for this purpose, SharpDevelop contains a hard-coded list of .NET assemblies).
Second: I found the MSBuild warning really annoying - it appears once per reference, so that's a few hundred warnings in a large solution. SharpDevelop 4.0 now simply ignores MSB3644.
Together, these two small changes make builds of .NET 4.0 projects work as expected, even if no Windows SDK is installed.
By the way: you can also use our workaround for the "copy local" bug in command line builds: call MSBuild with the parameter /p:CustomAfterMicrosoftCommonTargets=path-to-sharpdevelop\bin\SharpDevelop.TargetingPack.targets