ในโครงการก่อนหน้านี้ฉันทำงานกับโซลูชันขนาดใหญ่ที่อ้างอิงโครงการและชนกับปัญหาด้านประสิทธิภาพเช่นกัน คำตอบคือสามเท่า:
ตั้งค่าคุณสมบัติการคัดลอกภายในเครื่องเป็นเท็จเสมอและบังคับใช้ผ่านขั้นตอน msbuild ที่กำหนดเอง
ตั้งค่าไดเรกทอรีผลลัพธ์สำหรับแต่ละโครงการเป็นไดเรกทอรีเดียวกัน (โดยเฉพาะที่สัมพันธ์กับ $ (SolutionDir)
เป้าหมาย cs เริ่มต้นที่มาพร้อมกับเฟรมเวิร์กคำนวณชุดการอ้างอิงที่จะคัดลอกไปยังไดเรกทอรีผลลัพธ์ของโครงการที่กำลังสร้าง เนื่องจากต้องมีการคำนวณการปิดสกรรมกริยาภายใต้ความสัมพันธ์ 'การอ้างอิง' จึงอาจมีราคาแพงมาก วิธีแก้ปัญหาของฉันสำหรับการนี้คือการสร้างนิยามGetCopyToOutputDirectoryItems
เป้าหมายในไฟล์เป้าหมายร่วมกัน (เช่น. Common.targets
) Microsoft.CSharp.targets
ที่นำเข้าในทุกโครงการหลังจากนำเข้าของ ทำให้ไฟล์โครงการทุกไฟล์มีลักษณะดังนี้:
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
... snip ...
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="[relative path to Common.targets]" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
สิ่งนี้ลดเวลาการสร้างของเราในเวลาที่กำหนดจากสองสามชั่วโมง (ส่วนใหญ่เนื่องจากข้อ จำกัด ของหน่วยความจำ) เป็นสองถึงสามนาที
GetCopyToOutputDirectoryItems
สามารถสร้างนิยามใหม่ได้โดยการคัดลอกบรรทัด 2,438–2,450 และ 2,474–2,524 C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Microsoft.Common.targets
เข้าCommon.targets
มา
เพื่อความสมบูรณ์ของการกำหนดเป้าหมายผลลัพธ์ที่ได้จะกลายเป็น:
<!-- This is a modified version of the Microsoft.Common.targets
version of this target it does not include transitively
referenced projects. Since this leads to enormous memory
consumption and is not needed since we use the single
output directory strategy.
============================================================
GetCopyToOutputDirectoryItems
Get all project items that may need to be transferred to the
output directory.
============================================================ -->
<Target
Name="GetCopyToOutputDirectoryItems"
Outputs="@(AllItemsFullPathWithTargetPath)"
DependsOnTargets="AssignTargetPaths;_SplitProjectReferencesByFileExistence">
<!-- Get items from this project last so that they will be copied last. -->
<CreateItem
Include="@(ContentWithTargetPath->'%(FullPath)')"
Condition="'%(ContentWithTargetPath.CopyToOutputDirectory)'=='Always' or '%(ContentWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'"
>
<Output TaskParameter="Include" ItemName="AllItemsFullPathWithTargetPath"/>
<Output TaskParameter="Include" ItemName="_SourceItemsToCopyToOutputDirectoryAlways"
Condition="'%(ContentWithTargetPath.CopyToOutputDirectory)'=='Always'"/>
<Output TaskParameter="Include" ItemName="_SourceItemsToCopyToOutputDirectory"
Condition="'%(ContentWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'"/>
</CreateItem>
<CreateItem
Include="@(_EmbeddedResourceWithTargetPath->'%(FullPath)')"
Condition="'%(_EmbeddedResourceWithTargetPath.CopyToOutputDirectory)'=='Always' or '%(_EmbeddedResourceWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'"
>
<Output TaskParameter="Include" ItemName="AllItemsFullPathWithTargetPath"/>
<Output TaskParameter="Include" ItemName="_SourceItemsToCopyToOutputDirectoryAlways"
Condition="'%(_EmbeddedResourceWithTargetPath.CopyToOutputDirectory)'=='Always'"/>
<Output TaskParameter="Include" ItemName="_SourceItemsToCopyToOutputDirectory"
Condition="'%(_EmbeddedResourceWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'"/>
</CreateItem>
<CreateItem
Include="@(Compile->'%(FullPath)')"
Condition="'%(Compile.CopyToOutputDirectory)'=='Always' or '%(Compile.CopyToOutputDirectory)'=='PreserveNewest'">
<Output TaskParameter="Include" ItemName="_CompileItemsToCopy"/>
</CreateItem>
<AssignTargetPath Files="@(_CompileItemsToCopy)" RootFolder="$(MSBuildProjectDirectory)">
<Output TaskParameter="AssignedFiles" ItemName="_CompileItemsToCopyWithTargetPath" />
</AssignTargetPath>
<CreateItem Include="@(_CompileItemsToCopyWithTargetPath)">
<Output TaskParameter="Include" ItemName="AllItemsFullPathWithTargetPath"/>
<Output TaskParameter="Include" ItemName="_SourceItemsToCopyToOutputDirectoryAlways"
Condition="'%(_CompileItemsToCopyWithTargetPath.CopyToOutputDirectory)'=='Always'"/>
<Output TaskParameter="Include" ItemName="_SourceItemsToCopyToOutputDirectory"
Condition="'%(_CompileItemsToCopyWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'"/>
</CreateItem>
<CreateItem
Include="@(_NoneWithTargetPath->'%(FullPath)')"
Condition="'%(_NoneWithTargetPath.CopyToOutputDirectory)'=='Always' or '%(_NoneWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'"
>
<Output TaskParameter="Include" ItemName="AllItemsFullPathWithTargetPath"/>
<Output TaskParameter="Include" ItemName="_SourceItemsToCopyToOutputDirectoryAlways"
Condition="'%(_NoneWithTargetPath.CopyToOutputDirectory)'=='Always'"/>
<Output TaskParameter="Include" ItemName="_SourceItemsToCopyToOutputDirectory"
Condition="'%(_NoneWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'"/>
</CreateItem>
</Target>
ด้วยวิธีการแก้ปัญหาในสถานที่นี้ฉันพบว่าสามารถทำงานได้มากถึง> 120 โครงการในโซลูชันเดียวสิ่งนี้มีประโยชน์หลักที่การสร้างลำดับของโครงการยังสามารถกำหนดได้โดย VS แทนที่จะทำด้วยมือโดยแยกโซลูชันของคุณ .