2011-09-01 5 views
7

Quiero perfilar y ajustar nuestra construcción con la esperanza de ahorrar unos segundos aquí y allá. Yo era capaz de crear una tarea que se deriva de ResolveAssemblyReferences y utilizarla en su lugar, pero estoy teniendo problemas para entender lo siguiente (de Microsoft.Common.targets): se pasan¿Cómo funciona 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> 

Algunos parámetros y algunos se devuelven , pero ¿dónde sucede el trabajo real? No hay mucho en msdn: he encontrado Microsoft.Build.Tasks.ResolveProjectBase, pero no sirve de mucho.

Respuesta

12

ResolveProjectReferences (al menos el que está señalando) es un objetivo que se utiliza para resolver referencias entre proyectos mediante su construcción mediante la tarea <MSBuild>. Esta tarea requiere la creación de un archivo de proyecto, así como los nombres de uno o más objetivos del proyecto que deben invocarse como parte de la compilación (también toma otros parámetros, pero puede ignorarlos por ahora).

Considérese el siguiente objetivo:

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

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

Si ha hecho referencia a un proyecto que contiene este objetivo, y quería resolver las salidas del objetivo "Foo", que tendría un > elemento < ProjectReference en su proyecto, así:

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

Tenga en cuenta que, si "construir" es el destino predeterminado para el proyecto de referencia, usted podría dejar los "Objetivos" metadatos por completo. También puede especificar objetivos múltiples en los metadatos de objetivos (una lista delimitada por punto y coma).

Por lo tanto, su objetivo ResolveProjectReferences aparecerá y llamará a <MSBuild> task, pasándolo ".. \ SomeProject \ SomeProject.proj" y pidiéndole que cree el objetivo "Build". Ahora, dado que el objetivo "Build" especifica salidas a través de su atributo Returns (pero el atributo Outputs se usará si no se especifica el atributo Returns), estas salidas se recolectarán durante la compilación y se devolverán al parámetro <MSBuild> TargetOutputs . Tienen varias piezas adicionales de metadatos añadidos que te permiten segregarlos según el objetivo de origen. Estos incluyen:

  • MSBuildSourceProjectFile - el proyecto de referencia cuya acumulación generado la salida
  • MSBuildSourceTargetName - el nombre del objetivo cuya acumulación generado la salida

Si está trabajando en un proyecto de C#, hay un montón de otras etapas de resolución de referencia (incluida la resolución de ensamblaje). Envíame una línea si quieres saber sobre esto.

+0

Entonces, si resulta que la etapa ResolveProjectReferences está tomando cantidades significativas de tiempo durante una compilación, ¿eso es efectivamente porque el proyecto está bloqueado, esperando o se va a crear una dependencia? No he podido encontrar ninguna documentación clara sobre esto. No está claro si este es el tiempo dedicado a identificar y localizar dependencias (trabajo real), o el tiempo empleado esperando que las dependencias estén disponibles (tiempo de inactividad efectivo) – jalf

+0

Su mejor opción es construir en el nivel de verbosidad de diagnóstico. Eso le mostrará exactamente lo que hace cada objetivo (incluidas las construcciones anidadas), así como los tiempos para muchas operaciones. – tintoy