Today I saw a question on StackOverflow asking about the difference between DependsOnTargets and BeforeTargets/AfterTargets. Below is my response.
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.
DependsOnTargets versus Before/AfterTargets
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
- When you are trying to create a workflow of targets to be executed
- When a target will not function without the other target(s) executing first
- When you need to inject different targets at specific steps based on the desired operation
Use Before/AfterTargets when
- When you don't own the file the target resides in and it has no DependsOnTargets property that can be extended
- You want a target to execute Before/After a specific target no matter when it gets executed
To tease out the difference a bit consider web projects. For web projects there are two workflows that the .csproj/.vbproj take care of: 1. Build 1. Publish
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.
- All targets have a DependsOnTargets attribute which is feed by a property
- Each DependsOnTargets always prepends the existing value to the property definition
<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.