MSBuild and Custom Targets: Almost too much fun
I’m a big believer in DRY – Don’t Repeat Yourself – in software.
While I try hard to practice this in the code for the Bag of Tricks (BOT), until recently I’ve ignored my project files.
VS handles that, right?
Well, kind.
It turns out there is a lot of duplication in proj files. Every one defines constants and output paths. If you’re using Code Contracts, you get a bunch of contract properties all over – sometimes differing in inexplicable ways between debug and release.
I got sick of it. I cleaned it up.
- BuildShared.targets – Shared state across every project. Warning levels, shared build constants, even output path.
- This is great. If I want to change the location of obj and bin, I just change one file now. Super nice.
- Contracts.targets – This defines all of the Code Contracts build parameters.
- WPF4, SL4, WP7.targets – Common code for a given platform. Things like target framework, framework profile, etc. (WPF and SL include Contracts, Phone dosen’t.)
- Now each proj file includes the associated platform proj file and just sets project-specific properties.
- Guids, OutputType (library or exe), root namespace, assembly name, etc.
The downside: if you go hack specific properties via VS, you’ll add a bunch of one-off changes to individual proj files.
…but this is why we use source control, right? I can look at the diffs and ask: are these changes I want to share across projects or things I can just throw-away?
And having all of the shared noise in another place makes parsing the proj file a lot faster.
Take a look at the code. All of the targets are in PixelLab.Common\_targets. (Yeah, a weird place. I’ll explain later.)
Happy hacking.