編寫 Target 檢測 MSBuild / dotnet build 此次編譯是否是差量編譯
MSBuild 或 Roslyn 編譯專案時均支援差量編譯,畢竟為了效能。我在ofollow,noindex" target="_blank">每次都要重新編譯?太慢!讓跨平臺的 MSBuild/dotnet build 的 Target 支援差量編譯 一文中介紹瞭如何使一個 Target 支援差量編譯。在那篇文章中我說到差量編譯會導致 Target 不執行;也就是說,如果一個 Target 對後續的編譯會產生影響,那麼一定不能設定為差量編譯。
不過,真的會寫出一些非常耗時的 Target,但是它會對後續的編譯產生影響。這些 Target 如果要做差量編譯,那麼就不能直接使用原生的差量編譯方案了。本文將介紹如何處理這樣的情況。
我們遇到的問題
SourceFusion 是一個預編譯框架,它在你編譯期間對你的程式碼做一些改變。dotnet-campus/SourceFusion: SourceFusion is a pre-compile framework based on Roslyn. It helps you to build high-performance .NET code. 。
這意味著,這個耗時的 Target 是會改變後續的編譯的,典型的是 —— 它會在編譯期間增加和刪除幾個原始碼檔案。如果完全使用 Target 原生的差量編譯,那麼一旦這個 Target 跳過,那麼也就不會增加和刪除任何原始碼檔案了。
解決方案
解決方案是,我們寫一個前置的 Target,這個 Target 支援差量編譯。於是我們可以利用它的差量編譯特性得知當前是否處於差量編譯的狀態。
<Target Name="_WalterlvDemoRebuildingTest" BeforeTargets="WalterlvDemoCoreTarget" Inputs="$(MSBuildProjectFullPath)" Outputs="$(WalterlvDemoFolder)RebuildingTest.txt"> <PropertyGroup> <WalterlvDemoRebuildRequired>true</WalterlvDemoRebuildRequired> </PropertyGroup> <ItemGroup> <RebuildingTestLine Include="true" /> </ItemGroup> <WriteLinesToFile File="$(WalterlvDemoFolder)RebuildingTest.txt" Lines="@(RebuildingTestLine)" Overwrite="True" /> </Target>
上面的 Target 中,_WalterlvDemoRebuildingTest
是我給這個差量編譯測試 Target 取的名字,WalterlvDemoCoreTarget
是那個耗時的 Target。
根據我在每次都要重新編譯?太慢!讓跨平臺的 MSBuild/dotnet build 的 Target 支援差量編譯
一文中的差量編譯的做法,我使用$(MSBuildProjectFullPath)
也就是 csproj 檔案的改變來決定差量檢測的輸入,用一個臨時的檔案RebuildingTest.txt
來決定差量編譯的輸出。
在這裡,我們一定需要一個檔案來輸出,這樣 MSBuild 或者 Roslyn 檢測差量的時候才能正確完成。這樣,為了得到這個檔案,我們實際上需要通過這個 Target 真的寫一個檔案出來,所以我們用了WriteLinesToFile
。
實際上,我們真正需要的是WalterlvDemoRebuildRequired
這個屬性。我們可以通過這個屬性判斷為true
來得知當前並非差量狀態,而是需要重新編譯。
後續使用
對於我們真實的耗時的 Target,則需要檢測這個WalterlvDemoRebuildRequired
的值,進行不同的處理。
<Target Name="WalterlvDemoCoreTarget" BeforeTargets="CoreCompile"> <PropertyGroup> <WalterlvDemoRebuildRequired Condition="'$(WalterlvDemoRebuildRequired)' == ''">false</WalterlvDemoRebuildRequired> </PropertyGroup> <Exec ConsoleToMSBuild="True" Command="WalterlvDemo.exe -r $(WalterlvDemoRebuildRequired)" /> </Target>
我們在核心的 Target 裡面判斷WalterlvDemoRebuildRequired
的值,如果沒有被設定,說明前面的 Target 沒有執行,也就是“被差量”了,我們就可以將之指定為 false。
這樣,核心的 Target 裡面,也就是 WalterlvDemo.exe 執行引數中,就可以拿到正確的差量狀態了。true
表示正在重新編譯,而false
表示正在差量編譯。