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.
The Problem
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.
The Solution
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.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<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 BeforeTargets
or 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 Inputs
and 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:
_WalterlvDemoRebuildingTest
The Target that supports the incremental building_WalterlvDemoRebuildingTestInitialize
The Target to assign a value to propertySourceFusionRebuildRequired
WalterlvDemoCoreTarget
The 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.
I need 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.
1
2
3
4
5
6
<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 _WalterlvDemoRebuildingTestInitialize
Target.
Then pass the property value to the core Task, and the Task will know whether it is completely rebuilding or incremental building.
References
- CallTarget Task - Visual Studio - Microsoft Docs
- How to: Build Incrementally - Visual Studio - Microsoft Docs
- Property Functions - Visual Studio - Microsoft Docs
本文会经常更新,请阅读原文: https://blog.walterlv.com/post/detecting-rebuild-switch-using-msbuild-target-en.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名 吕毅 (包含链接: https://blog.walterlv.com ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系 ([email protected]) 。