Here is the twist: By adding import statements that looks for target files in specific directories and following a naming pattern, every project can have its own MSBuild files that are imported before and after the main definitions in the Microsoft.Common.targets file.
The result is that every project in a solution will build the exactly way you want them to. Even when you build your solution inside Visual Studio! The solution targets files will affect every project, while the project targets file will only affect the specific project.
There are a number of things one can do with this mechanism. Here are some examples:
- Change the way version numbers are updated when building. How about leaving AssemblyInfo.cs alone and let a build task update the AssemblyVersion and AssemblyFileVersion attributes automatically, by e.g. picking up $(CCNetLabel) set by CruiseControl.Net
- Change the $(AssemblySearchPaths) property to have a more restrictive resolving of references in a build. We don't want Visual Studio to go looking for assemblies to "help us"
- Suppress those annoying "missing xml comments" warnings that no-one cares about anyway.
- Inserting targets into $(BuildDependsOn) that are called before or after build, instead of using those nasty pre- and post-build steps that you specify in the project properties dialogue.
Download the source here
So why bother implementing a practice like this instead of just putting all your custom behavior into the custom target files themselves? Well, by doing that, you will affect all kinds of projects. By importing solution and project level MSBuild files if they are there, the projects and solutions themselves can decide exactly how they want to be built.
A couple of caveats:
- If you mess up your solution and project level MSBuild files, you may get your VS rendered useless until you fix the problems. The only way is to edit your files without loading the solution and test it with MSBuild at the VS command prompt.
- If you edit your solution and project build files from within your solution in VS, then you have to close the solution and reopen it to get them applied. I guess VS caches the build definitions to be able to resolve references, etc.