Write a MSBuild Target to detect whether the project is rebuilding or not
MSBuild or the dotnet build command both supports Incremental Building for compiling performance. You can read How to: Build Incrementally - Visual Studio - Microsoft Docs to lean more about incremental building. When a target supports increment building and the project is rebuilding for the moment, the Target will not execute. So if it affects followed other Targets, it cannot be set to incremental building.
But how can I detect a incremental building behavior and do something different things if my Target affects followed other Targets? In this post, I’ll talk about that.
SourceFusion is a pre-compile framework and allows you to change you code during the compiling. You can visit dotnet-campus/SourceFusion: SourceFusion is a pre-compile framework based on Roslyn. It helps you to build high-performance .NET code. to view the open-source project.
The Target in the SourceFusion takes long time and affects followed Targets such as the
CoreCompile Target. If it use a completely incremental building, the Target will be skipped when building and no more source code will be added or removed before the
CoreCompile Target. So nothing will happen during a incremental building and the SourceFusion changes nothing.
We can write another Target helps us to detect rebuilding behavior. We can define a property to tell us whether it is a incremental building or not.
<Target Name="_WalterlvDemoRebuildingTest" BeforeTargets="WalterlvDemoCoreTarget" Inputs="$(MSBuildProjectFullPath)" Outputs="$(WalterlvDemoFolder)RebuildingTest.txt"> <ItemGroup> <RebuildingTestLine Include="true" /> </ItemGroup> <CallTarget Targets="_WalterlvDemoRebuildingTestInitialize" /> <WriteLinesToFile File="$(WalterlvDemoFolder)RebuildingTest.txt" Lines="@(RebuildingTestLine)" Overwrite="True" /> </Target> <Target Name="_WalterlvDemoRebuildingTestInitialize"> <PropertyGroup> <WalterlvDemoRebuildRequired>true</SourceFusionRebuildRequired> </PropertyGroup> </Target>
In this code, I write two Targets and the second one doesn’t define any
AfterTargets attributes. So this Target will not be executed automatically unless you call it explicitly. I define a property named
SourceFusionRebuildRequired in it to flag the rebuilding status.
I call this separated Target in the first target which defines
Outputs attributes. We can know that if a Target want to support incremental building the two attributes are important. So this Target supports that.
These are the three mentioned Targets:
_WalterlvDemoRebuildingTestThe Target that supports the incremental building
_WalterlvDemoRebuildingTestInitializeThe Target to assign a value to property
WalterlvDemoCoreTargetThe long-time Target that will use the incremental building test value
I use a csproj file as a input file and another temp file as a output file. Then if a project file changed and a rebuilding will happen. To generate a temp output file I should use
WriteLinesToFile Task to write one.
WalterlvDemoRebuildRequired property to detect the rebuilding behavior. If the project is rebuilding the property will be assigned because the
_WalterlvDemoRebuildingTestInitialize is called and if the project is incremental building the property will not be assigned.
Then we can check the value of
WalterlvDemoRebuildRequired to detect a rebuilding or incremental building.
How to use this property
For the long-time Target
WalterlvDemoCoreTarget, it should detect the property and do something different.
<Target Name="WalterlvDemoCoreTarget" BeforeTargets="CoreCompile"> <PropertyGroup> <WalterlvDemoRebuildRequired Condition="'$(WalterlvDemoRebuildRequired)' == ''">false</WalterlvDemoRebuildRequired> </PropertyGroup> <Exec ConsoleToMSBuild="True" Command="WalterlvDemo.exe -r $(WalterlvDemoRebuildRequired)" /> </Target>
We define the same property only if it is not been assigned. But we assign it as a
false value which is different to the
Then pass the property value to the core Task, and the Task will know whether it is completely rebuilding or incremental building.
- CallTarget Task - Visual Studio - Microsoft Docs
- How to: Build Incrementally - Visual Studio - Microsoft Docs
- Property Functions - Visual Studio - Microsoft Docs
本文会经常更新，请阅读原文： https://walterlv.com/post/detecting-rebuild-switch-using-msbuild-target-en.html ，以避免陈旧错误知识的误导，同时有更好的阅读体验。
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布，但务必保留文章署名 吕毅 （包含链接： https://walterlv.com ），不得用于商业目的，基于本文修改后的作品务必以相同的许可发布。如有任何疑问，请 与我联系 (email@example.com) 。