2015-05-22 14 views
5

Sto cercando di accelerare la compilazione di un set di soluzioni compilando solo una volta i progetti condivisi. Questa è una descrizione semplificata del mio problema.Perché MSBuild sta ricostruendo progetti condivisi?

Ho due soluzioni: uno.sln e due.sln. Entrambi includono il progetto condiviso shared.csproj. Apro le due soluzioni in Visual Studio, pulisco entrambe, quindi costruisco one.sln, quindi creo two.sln. Quando due.sln è compilato, shared.dll NON viene rigenerato, che è il comportamento che mi aspetto.

Per automatizzare questo processo, ho creato un file .proj di msbuild (sotto). Quando chiamo msbuild sul file .proj, shared.dll viene ricompilato per le soluzioni BOTH. Che cosa sto facendo di sbagliato?

<Project ToolsVersion="4.0" 
     xmlns="http://schemas.microsoft.com/developer/msbuild/2003" 
     DefaultTargets="Build"> 
    <ItemGroup> 
     <Solution Include="C:\one.sln"/> 
     <Solution Include="C:\two.sln"/> 
    </ItemGroup> 
    <Target Name="Build"> 
     <MSBuild Projects="@(Solution)" Targets="Build" RunEachTargetSeparately="false" StopOnFirstFailure="true" /> 
    </Target> 
</Project> 

risposta

3

IIRC, il motivo per cui è stato compilato il riferimento due volte, è che si è dichiarato come un progetto di riferimento in entrambe le soluzioni. Quindi entrambi chiameranno la Build Target del loro riferimento. Ecco come lo capisco.

Creare un ItemGroup per il progetto di riferimento

<!--Project reference--> 
    <ItemGroup> 
    <ProjectReference Include="refProject\refProject.csproj"> 
     <Targets>Build</Targets> 
    </ProjectReference> 
    </ItemGroup> 

Aggiungi un target di riferimento per costruire

<Target Name="ComputeProjectReference" Inputs="@(ProjectReference)" Outputs="%(ProjectReference.Identity)__Forced"> 
    <MSBuild Projects="@(ProjectReference)" Targets="%(ProjectReference.Targets)"> 
     <Output TaskParameter="TargetOutputs" ItemName="ResolvedProjectReferences"/> 
    </MSBuild> 
    </Target> 

    <Target Name="AfterProjectReference" AfterTargets="ComputeProjectReference"> 
    <CreateItem Include="@(ResolvedProjectReferences)"> 
     <Output TaskParameter="Include" ItemName="CopyFiles" /> 
    </CreateItem> 

    <Copy SourceFiles="@(CopyFiles)" DestinationFolder="$(AssemblyName)\$(OutputPath)" SkipUnchangedFiles="false" /> 

    <ItemGroup> 
     <NewAssemblies Include="$(AssemblyName)\$(OutputPath)%(CopyFiles.FileName)%(CopyFiles.Extension)" /> 
    </ItemGroup> 

    </Target> 

Purtroppo, compito MSBuild non prende riferimenti come parametro. Suggerisco di creare gruppi di articoli che rappresentano ciascun progetto richiesto. qualcosa come

<ItemGroup> 
    <CompileA Include="ConsProject\Program.cs" /> 
    <CompileA Include="ConsProject\Properties\AssemblyInfo.cs" /> 
    <CompileA Include="ConsProject\Properties\Settings.Designer.cs"> 
     <AutoGen>True</AutoGen> 
     <DesignTimeSharedInput>True</DesignTimeSharedInput> 
     <DependentUpon>Settings.settings</DependentUpon> 
    </CompileA> 
    </ItemGroup> 

    <ItemGroup> 
    <CompileB Include="OtherProject\Program.cs" /> 
    <CompileB Include="OtherProject\Properties\AssemblyInfo.cs" /> 
    <CompileB Include="OtherProject\Properties\Settings.Designer.cs"> 
     <AutoGen>True</AutoGen> 
     <DesignTimeSharedInput>True</DesignTimeSharedInput> 
     <DependentUpon>Settings.settings</DependentUpon> 
    </CompileB> 
    </ItemGroup> 

E creare un obiettivo di costruire i progetti con i riferimenti compilati una volta

<!--Build Process--> 
    <Target Name="Build" DependsOnTargets="ComputeProjectReference" > 
    <Csc Sources="@(CompileA)" References="@(NewAssemblies)" TargetType="exe" OutputAssembly="$(AssemblyName)\$(OutputPath)\$(AssemblyName).exe" /> 

    <Csc Sources="@(CompileB)" References="@(NewAssemblies)" TargetType="exe" OutputAssembly="$(AssemblyName)\$(OutputPath)\$(AssemblyName).exe" /> 

    </Target> 
1

ho capito il motivo per cui i progetti condivisi venivano ricompilati per ogni soluzione. Abbiamo una fase di post-produzione in ogni progetto che il codice firma il file di destinazione. Dopo ogni precedente compilazione di un progetto, il file .dll è più recente del file .pdb, quindi ricompila il progetto. Ho trovato questo fuori usando l'opzione/v: d per la registrazione dettagliata, quindi cercando "completamente" nell'output per scoprire perché i progetti venivano creati completamente ogni volta.

Problemi correlati