2011-09-01 4 views
7

Voglio profilare e modificare la nostra build sperando di risparmiare qualche secondo qua e là. Sono stato in grado di creare un compito che deriva da ResolveAssemblyReferences e utilizzarlo invece, ma sto avendo problemi nel comprendere la seguente (da Microsoft.Common.targets):Come funziona ResolveProjectReferences?

<!-- 
    ============================================================ 
             ResolveProjectReferences 

    Build referenced projects: 

     [IN] 
     @(NonVCProjectReference) - The list of non-VC project references. 

     [OUT] 
     @(_ResolvedProjectReferencePaths) - Paths to referenced projects. 
    ============================================================ 
    --> 
    <Target 
     Name="ResolveProjectReferences" 
     DependsOnTargets="SplitProjectReferencesByType;_SplitProjectReferencesByFileExistence"> 

     <!-- 
     When building this project from the IDE or when building a .SLN from the command-line, 
     just gather the referenced build outputs. The code that builds the .SLN will already have 
     built the project, so there's no need to do it again here. 

     The ContinueOnError setting is here so that, during project load, as 
     much information as possible will be passed to the compilers. 
     --> 
     <MSBuild 
      Projects="@(_MSBuildProjectReferenceExistent)" 
      Targets="GetTargetPath" 
      BuildInParallel="$(BuildInParallel)" 
      UnloadProjectsOnCompletion="$(UnloadProjectsOnCompletion)" 
      Properties="%(_MSBuildProjectReferenceExistent.SetConfiguration); %(_MSBuildProjectReferenceExistent.SetPlatform)" 
      Condition="'@(NonVCProjectReference)'!='' and ('$(BuildingSolutionFile)' == 'true' or '$(BuildingInsideVisualStudio)' == 'true' or '$(BuildProjectReferences)' != 'true') and '@(_MSBuildProjectReferenceExistent)' != ''" 
      ContinueOnError="!$(BuildingProject)"> 

      <Output TaskParameter="TargetOutputs" ItemName="_ResolvedProjectReferencePaths"/> 
     </MSBuild> 

     <!-- 
     Build referenced projects when building from the command line. 

     The $(ProjectReferenceBuildTargets) will normally be blank so that the project's default 
     target is used during a P2P reference. However if a custom build process requires that 
     the referenced project has a different target to build it can be specified. 
     --> 
     <MSBuild 
      Projects="@(_MSBuildProjectReferenceExistent)" 
      Targets="$(ProjectReferenceBuildTargets)" 
      BuildInParallel="$(BuildInParallel)" 
      UnloadProjectsOnCompletion="$(UnloadProjectsOnCompletion)" 
      Condition="'@(NonVCProjectReference)'!='' and '$(BuildingInsideVisualStudio)' != 'true' and '$(BuildingSolutionFile)' != 'true' and '$(BuildProjectReferences)' == 'true' and '@(_MSBuildProjectReferenceExistent)' != ''"> 
      <Output TaskParameter="TargetOutputs" ItemName="_ResolvedProjectReferencePaths"/> 

     </MSBuild> 

     <!-- 
     Get manifest items from the (non-exe) built project references (to feed them into ResolveNativeReference). 
     --> 
     <MSBuild 
      Projects="@(_MSBuildProjectReferenceExistent)" 
      Targets="GetNativeManifest" 
      BuildInParallel="$(BuildInParallel)" 
      UnloadProjectsOnCompletion="$(UnloadProjectsOnCompletion)" 
      Properties="%(_MSBuildProjectReferenceExistent.SetConfiguration); %(_MSBuildProjectReferenceExistent.SetPlatform)" 
      Condition="'@(NonVCProjectReference)'!='' and '$(BuildingProject)'=='true' and '@(_MSBuildProjectReferenceExistent)'!=''"> 

      <Output TaskParameter="TargetOutputs" ItemName="NativeReference"/> 

     </MSBuild> 


     <!-- Issue a warning for each non-existent project. --> 
     <Warning 
      Text="The referenced project '%(_MSBuildProjectReferenceNonexistent.Identity)' does not exist." 
      Condition="'@(NonVCProjectReference)'!='' and '@(_MSBuildProjectReferenceNonexistent)'!=''"/> 
    </Target> 

Alcuni parametri sono passati e alcuni vengono restituiti , ma dove avviene il vero lavoro? Non c'è molto su msdn - Ho trovato Microsoft.Build.Tasks.ResolveProjectBase, ma non è molto utile.

risposta

12

ResolveProjectReferences (almeno quello a cui si punta) è un obiettivo utilizzato per risolvere i riferimenti tra progetti costruendoli utilizzando l'attività <MSBuild>. Questa attività richiede un file di progetto da compilare, così come i nomi di uno o più target nel progetto che dovrebbero essere richiamati come parte della build (ci vogliono anche altri parametri, ma per ora puoi ignorarli).

Si consideri il seguente obiettivo:

<Target 
    Name="Build" 
    Returns="@(BuildOutput)"> 

    <ItemGroup> 
    <BuildOutput Include="bin\Debug\Foo.exe" /> 
    </ItemGroup> 
</Target> 

Se si fa riferimento un progetto contenente questo obiettivo, e ha voluto per risolvere le uscite del bersaglio "foo", si avrebbe un <ProjectReference> elemento nel progetto in questo modo:

<ItemGroup> 
    <ProjectReference Include="..\SomeProject\SomeProject.proj"> 
    <Targets>Build</Targets> 
    </ProjectReference> 
</ItemGroup> 

si noti che, se "costruire" è la destinazione predefinita per il progetto di riferimento, si potrebbe lasciare gli "obiettivi" metadati fuori del tutto. Puoi anche specificare più target nei metadati Targets (un elenco delimitato da punto e virgola).

Quindi il tuo obiettivo ResolveProjectReferences arriverà e chiamerà l'attività MSBuild >, passandola ".. \ SomeProject \ SomeProject.proj" e chiedendole di creare il target "Build". Ora, dato che la destinazione "Build" specifica gli output tramite l'attributo Returns (ma l'attributo Outputs verrà utilizzato se l'attributo Returns non è specificato), questi output verranno raccolti durante la build e restituiti al parametro TargetOutputs delle attività > delle attività MSBuild > . Hanno aggiunto diversi metadati aggiuntivi che consentono di separarli dall'origine del target. Questi includono:

  • MSBuildSourceProjectFile - il progetto di riferimento il cui accumulo generato l'uscita
  • MSBuildSourceTargetName - il nome del target cui accumulo generato l'uscita

Se stai lavorando all'interno di un progetto di C#, ci sono un sacco di altre fasi di risoluzione di riferimento (compresa la risoluzione dell'assemblaggio). Lasciami una riga se vuoi sapere di questi.

+0

Quindi, se si scopre che la fase ResolveProjectReferences sta impiegando una quantità significativa di tempo durante una compilazione, è effettivamente perché il progetto è bloccato, in attesa o una dipendenza da costruire? Non sono stato in grado di trovare alcuna documentazione chiara su questo. Non è chiaro se si tratti di tempo dedicato all'individuazione e all'individuazione delle dipendenze (lavoro effettivo) o del tempo trascorso in attesa che le dipendenze diventino disponibili (tempo di inattività effettivo) – jalf

+0

La soluzione migliore è costruire a livello di livello di dettaglio Diagnostica. Questo ti mostrerà esattamente cosa sta facendo ogni bersaglio (incluse le build nidificate) e le tempistiche per molte operazioni. – tintoy