Reputation: 16209
Recently, I started to learn MSBuild in order to flexible build scripts for local as well as server builds (CI, Nightly, Weekly). Based on my experience I knew that build scripts can be very awkward. Even at my company with some guidance it was a pain to get to know all targets and how they work together. For sure, it was a long-term process: you need something, you don't have enough time, you start being lazy and messy. But I asked myself, how could I structure a MSBuild script for easy extensibility and readability? Especially the three relationships between targets DependsOnTargets, BeforeTargets, AfterTargets were useful to shoot myself in the foot.
Upvotes: 3
Views: 1053
Reputation: 44332
In my MSBuild Book I have a section based on how to create reusable elements in MSBuild, if you are interested. I'll give some comments here as well though. This content is different from what the book has.
When creating MSBuild files you should be careful to isolate what versus how. To explain that a bit, lets examine how the managed VS projects work out of the box (which is a great model for reusable elements).
When you create a C#/VB project you get a .csproj file, this .csproj file primarily contains Properties and Items. You will not find a single target in that file. These files contains what will get built (along with some settings relating to the build). At the bottom of the project file you will find an import statement. This import bring in How the project is built.
The files which are imported include:
In this case Microsoft.common.targets defines the overall build process for all the managed languages. Then Microsoft.CSharp.targets (or one of the other lang specific .targets file) fills in the blanks of how to invoke the specific language specific tools.
In your answer above you state "I recommend to avoid DependsOnTargets unless it is really really necessary, for instance if two". I disagree with this. Here is my take on DependsOnTargets versus Before/AfterTargets.
Use DependsOnTargets when
Use Before/AfterTargets when
To tease out the difference a bit consider web projects. For web projects there are two workflows that the .csproj/.vbproj take care of:
If I want to add a target to the list of targets to be executed before the Build target I can dynamically update the BuildDependsOn property for publish scenarios only. You cannot do this with Before/AfterTargets.
In an ideal world each target would have the following wrt DependsOnTargets.
For example
<MyTargetDependsOn>
$(MyTargetDependsOn);
Target1;
Target2
</MyTargetDependsOn>
Unfortunately many targets do not follow this pattern, so DependsOnTargets is dead in the water for many cases.
When I am authoring MSBuild scripts I always use DependsOnTargets unless there is a solid reason why I should chose to use Before/AfterTargets. I feel that (I have no insight on the real reasons to the design as I wasn't with Microsoft at the time) Before/AfterTargets was really created to allow users to inject targets to be executed before/after a target which they did not own, and the creators did not use the pattern above.
Upvotes: 7