Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Run an MSBuild target only if project is actually built

I have an MSBuild file that builds */.sln files (builds all .sln files that exist).

The build uses the Build target, so if no changes were made to input files, no project should be built again.

I would like to execute some custom target only if a project actually gets built again.

How can this be done?

Both AfterBuild and AfterCompile are always called, no matter if the compile/build actually takes place.

like image 982
lysergic-acid Avatar asked Dec 20 '12 13:12

lysergic-acid


People also ask

How do I run a target in MSBuild?

At the command line, type MSBuild.exe <SolutionName>. sln , where <SolutionName> corresponds to the file name of the solution that contains the target that you want to execute. Specify the target after the -target: switch in the format <ProjectName>:<TargetName>.

Will MSBuild compile without any target?

If there are no initial targets, default targets, or command-line targets, then MSBuild runs the first target it encounters in the project file or any imported project files.

What is the difference between MSBuild and Visual Studio build?

Visual Studio determines the build order and calls into MSBuild separately (as needed), all completely under Visual Studio's control. Another difference arises when MSBuild is invoked with a solution file, MSBuild parses the solution file, creates a standard XML input file, evaluates it, and executes it as a project.

What is MSBuild target?

A target element can have both Inputs and Outputs attributes, indicating what items the target expects as input, and what items it produces as output. If all output items are up-to-date, MSBuild skips the target, which significantly improves the build speed. This is called an incremental build of the target.


1 Answers

Basically you want the same behaviour as the PostBuildEvent for instance, so I looked up how Microsoft.Common.Targets does it (this file always provides a nice insight in to how msbuild is supposed to be used). Here's the solution:

<PropertyGroup>
  <RunPostBuildEvent>OnOutputUpdated</RunPostBuildEvent>
</PropertyGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="RunWhenBuild" AfterTargets="CoreBuild"       
        Condition="'$(_AssemblyTimestampBeforeCompile)'!='$(_AssemblyTimestampAfterCompile)'">
  <Message Importance="high" Text="RunWhenBuild!!"/>
</Target>

And this is what goes on: when there is a property named RunPostBuildEvent with a value of OnOutputUpdated the CoreBuild target's dependncies will eventually record the timestamp of the output file before and after the build. And if they are equal the output was not build. So all that is left is getting your target to run after CoreBuild and checking on these timestamps.

like image 163
stijn Avatar answered Nov 13 '22 22:11

stijn