Önceki bir projede, proje referanslarıyla birlikte büyük bir çözümle çalıştım ve bir performans sorunuyla da karşılaştım. Çözelti üç kat olmuştur:
Her zaman Yerel Kopyala özelliğini false olarak ayarlayın ve bunu özel bir msbuild adımı ile zorlayın
Her proje için çıkış dizinini aynı dizine ayarlayın (tercihen $ (SolutionDir) değerine göre)
Çerçeveyle birlikte gelen varsayılan cs hedefleri, o anda inşa edilen projenin çıktı dizinine kopyalanacak olan referans kümesini hesaplar. Bu, 'Referanslar' ilişkisi altında geçişli bir kapatmanın hesaplanmasını gerektirdiğinden, bu çok maliyetli olabilir. Bunun için geçici çözümüm, her bir projenin içe aktarılmasından sonra içe aktarılan GetCopyToOutputDirectoryItems
ortak hedefler dosyasında (ör. Common.targets
) Hedefi yeniden tanımlamaktı Microsoft.CSharp.targets
. Sonuç olarak her proje dosyasında aşağıdaki gibi görünün:
<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>
Bu, belirli bir zamanda yapım süremizi birkaç saatten (çoğunlukla bellek kısıtlamaları nedeniyle) birkaç dakikaya indirdi.
Yeniden tanımlanmış GetCopyToOutputDirectoryItems
olan 2,438–2,450 ve 2,474–2,524 satırlarını C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Microsoft.Common.targets
içine kopyalayarak oluşturulabilir Common.targets
.
Tamlık için, sonuçta elde edilen hedef tanım:
<!-- 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>
Bu geçici çözümle, tek bir çözümde 120'den fazla projeye sahip olmanın işe yaradığını gördüm, bu, projelerin derleme sırasının, çözümünüzü bölerek elle yapmak yerine VS tarafından belirlenebilmesinin ana avantajına sahiptir. .