Welcome to Manicprogrammer Sign in | Join | Help

Learning Something New on MSBuild Targets and Conditions

I love learning something new. Especially something that goes against what I would have expected. Such is the case with MSBuild Targets and conditions. A few days ago I posted about Enforcing Build Agents in a Team Build. I challenged others to show me the better way to do what I wanted and Ibrahim Hashimi took up the gauntlet and did just that. Actually, he has challenged that post twice now and I learn something each time. Go Ibrahim! The latest post on MSBuild Conditions in Targets was especially interesting. Though I didn't agree with Ibrahim about not using Conditions on targets when I began reading it he makes an interesting case in his example that I would not have expected to see and didn't realize would be the case. I have since joined him in thought. I know I will now be much more careful about how I use conditions with my targets to ensure I get the expected outcome.

I had planned to write out a post saying that what Ibrahim had failed to point out, though it made his point no less valid, is that this only occurs if you call the target explicitly such as in his example of msbuild /t:Demo or if you did the following calling msbuild /t:InitTarget.

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <Project ToolsVersion="2.0" 
   3:          xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
   4:          DefaultTargets="Demo"> 
   5:  
   6:   <PropertyGroup>
   7:     <AllowTarget>true</AllowTarget>
   8:   </PropertyGroup> 
   9:  
  10: <Target Name="InitTarget"> 
  11:  
  12:     <CallTarget Targets="Demo" /> 
  13:  
  14: </Target> 
  15:  
  16:   <Target Name="SupressTarget">
  17:     <CreateProperty Value="false">
  18:       <Output PropertyName="AllowTarget" TaskParameter="Value"/>
  19:     </CreateProperty>
  20:     <Message Text=" ==== SupressTarget ==== " Importance="high"/>
  21:     <Message Text="AllowTarget: $(AllowTarget)"/>
  22:   </Target> 
  23:  
  24:   <Target Name="Demo" Condition="'$(AllowTarget)'=='true'" 
  25:           DependsOnTargets="SupressTarget">
  26:     <Message Text=" ===== Demo ===== " Importance="high" /> 
  27:  
  28:     <Message Text="AllowTarget: $(AllowTarget)"/>
  29:   </Target>
  30: </Project>

 

I had then planned to go on and say (wrongly) that if you had it implicitly called as would be the case below you would get the often expected results of the Demo target not running- msbuild /t:InitTarget:

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <Project ToolsVersion="2.0" 
   3:          xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
   4:          DefaultTargets="Demo"> 
   5:  
   6:   <PropertyGroup>
   7:     <AllowTarget>true</AllowTarget>
   8:   </PropertyGroup> 
   9:  
  10: <Target Name="InitTarget" DependsOnTargets="Demo"> 
  11:  
  12:        <Message Text=" ===== InitTarget ===== " Importance="high" /> 
  13:  
  14: </Target> 
  15:  
  16:   <Target Name="SupressTarget">
  17:     <CreateProperty Value="false">
  18:       <Output PropertyName="AllowTarget" TaskParameter="Value"/>
  19:     </CreateProperty>
  20:     <Message Text=" ==== SupressTarget ==== " Importance="high"/>
  21:     <Message Text="AllowTarget: $(AllowTarget)"/>
  22:   </Target> 
  23:  
  24:   <Target Name="Demo" Condition="'$(AllowTarget)'=='true'" 
  25:           DependsOnTargets="SupressTarget">
  26:     <Message Text=" ===== Demo ===== " Importance="high" /> 
  27:  
  28:     <Message Text="AllowTarget: $(AllowTarget)"/>
  29:   </Target>
  30: </Project>

I had expected that since it set up my tree for execution by walking backwards up the dependencies the engine would say - Let's see you want to run InitTarget which means I need to include Demo which means I need to include SuppressTarget so here is what I'll run for you and evaluate if each target runs as I get to it:

  • SuppressTarget
  • Demo
  • InitTarget

Imagine my surprise when I ran the above script and got the following output:

targettest image

DOH!

Not what I expected. I would have bet the farm that as long as the target was not explicitly called but was executed based upon dependencies only that I would have received the results I expected. I would have lost the farm and man oh man would my wife have been upset. I suspect this is because I don't realize what that DependsUponTargets really gets translated into. Which is the point Ibrahim was making not about me specifically but about room for confusion in general. The target has already been chosen to exist and run. Very interesting. 

I plan to play around with this a bit more. It may bring to light I have some scripts that don't actually work the way I expect. Hmm... I must digest this.

Published Saturday, June 28, 2008 8:51 AM by michaelruminer
Filed under

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

Thursday, July 03, 2008 3:10 PM by Team System News

# VSTS Links - 07/03/2008

Michael Ruminer on Learning Something New on MSBuild Targets and Conditions and Visual Studio 2008 DB...


Enter the text you see in the image:

Leave a Comment

(required) 
required 
(required)