我的組織擁有一些運行在構建服務器上的巨大構建,構建大量以及大量與ProjectReferences鏈接的MSBUILD項目。我們需要能夠與msbuild /m
並行構建項目和配置。並行MSBUILD - 關鍵部分?
我的問題是我有一個項目引用了大量的其他項目,但項目本身是而不是可重入。如果多於兩個或更多節點試圖並行構建該項目,則會失敗。
如何將這一個項目或它的目標包裹在臨界區域內?
我真正需要做的是這樣的:
<Target>
<EnterCriticalSection ID=$(ProjectGuid) />
<Exec something />
<LeaveCriticalSection ID=$(ProjectGuid) />
</Target>
的想法是,如果多個MSBUILD節點試圖在並行建造這個項目,只有其中一個節點可以做執行,和其餘的節點將不得不等待(或者去做別的事情)。
我想我可以編寫自定義的MSBUILD任務來完成這個任務,但是在MSBUILD系統中沒有這樣的方法嗎?
===編輯4/5/13。爲了澄清,該項目正在使用爲其提供的構建腳本構建第三方庫。完全重寫他們的構建腳本以使其可重入 - 通過確保每個構建對中間文件使用不同的文件夾集合等 - 在理論上是可能的,但不是一個實際的解決方案。首先,所有這些工作都必須在該庫的每個新版本中重做。
===編輯4/6/13。經過進一步的思考,我認爲甚至在理論上也不可能確保項目是可重入的。讓我來解釋:
假設XYZ項目被設置爲使用依賴於平臺和配置以通常的方式不同的臨時目錄:
XYZ.proj:
<PropertyGroup>
<MyWorkingDir>tmp.$(Platform).$(Configuration)</MyWorkingDir>
</PropertyGroup>
現在假設其他一些項目GraphicsWindow通過ProjectReferences或MSBuild任務引用項目XYZ。假設GraphicsWindow項目可以構建爲使用各種圖形API。也就是說,有一個版本的OpenGL,DirectX的版本9,支持DirectX 10,版本...
所以某處有包含目標打造四個版本.proj或.targets文件:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ProjectToBuild Include="GraphicsWindow.proj">
<Properties>GraphicsApi=OpenGL</Properties>
</ProjectToBuild>
<ProjectToBuild Include="GraphicsWindow.proj">
<Properties>GraphicsApi=D3D9</Properties>
</ProjectToBuild>
<ProjectToBuild Include="GraphicsWindow.proj">
<Properties>GraphicsApi=D3D10</Properties>
</ProjectToBuild>
<ProjectToBuild Include="GraphicsWindow.proj">
<Properties>GraphicsApi=D3D11</Properties>
</ProjectToBuild>
</ItemGroup>
<Target Name="All">
<MSBuild Projects="@(ProjectToBuild)" BuildInParallel="true" />
</Target>
</Project>
或使用批處理的等價物。配置組合和相同的工作目錄|
現在的MSBuild將與相同平臺建設XYZ項目的4倍。
只要不使用/ m選項並且MSBuild運行單個線程,就可以正常工作。根據XYZ項目的編寫方式,第二,第三和第四個版本可能什麼也不做,因爲輸出是最新的,或者它可能會做一些重複的工作,但最終結果是正確的,並且構建會成功。
但是,只要你開始使用並行MSBuild,這個構建是打破了!現在有一個競爭條件,多個線程可以同時進入XYZ項目的目標,並使用相同的工作目錄開始構建,這將失敗。
您確定需要並行創建多個項目嗎? 「Msbuild」已經並行編譯並同時編譯多個源文件。嘗試並行執行多個版本可能會導致硬盤訪問瓶頸導致性能下降。 – SomeWittyUsername 2013-04-06 16:30:18