2009-06-02 5 views
28

¿Cuál es la diferencia entre la creación de un elemento dentro de un objetivo como éste:CreateItem vs ItemGroup

<Target Name="DoStuff"> 
    <CreateItem Include="@(IntermediateAssembly)" > 
     <Output TaskParameter="Include" ItemName="FileWrites"/> 
    </CreateItem> 
</Target> 

y como este:

<Target Name="DoStuff"> 
    <ItemGroup> 
     <FileWrites Include="@(IntermediateAssembly)" /> 
    </ItemGroup> 
</Target> 

¿Cuándo utilizar uno o el otro y por qué?

Respuesta

27

En versiones de MSBuild anteriores a 3.5 no se podían definir propiedades o elementos dentro de los destinos (como en el segundo ejemplo). Por lo tanto, se utilizó una tarea en su lugar (CreateItem y CreateProperty)

Si está utilizando ToolsVersion 3.5, entonces ya no necesita usar CreateItem (aunque puede hacerlo si lo prefiere).

Al final ambos crean el elemento de la misma manera, con el mismo alcance. Usar la segunda sintaxis es más legible y configurar metadatos personalizados es mucho más fácil (en mi opinión).

NOTA: La versión 3.5 de MSBuild está instalada con .NET 3.5. Aunque necesita definir ToolsVersion="3.5" en la etiqueta Project de su archivo MSBuild para usar las características 3.5.

En caso de que se lo pregunte, obtuve la mayor parte de esta información del libro Inside the Microsoft® Build Engine: Using MSBuild and Team Foundation Build que realmente me gustó (pero no estoy afiliado de ninguna manera).

+0

¡Muchas gracias, esto es justo lo que quería saber! Tendré que echarle un vistazo a ese libro. – Jake

+2

Sí, ese libro es genial, me encanta :) :) :) Gracias por el rec. –

+5

Sin embargo, encontré una gran diferencia: CreateItem expandirá los comodines que se le asignan en Incluir a través de una operación de transformación como mientras que una declaración ItemGroup no lo expandirá . –

7

No creo que la respuesta aceptada haya definido la diferencia.

La diferencia es:

  • ItemGroup se evalúa cuando se carga el script MSBuild.
  • CreateItem se evalúa cuando el objetivo es ejecutado

Esto puede dar lugar a diferentes valores del artículo dentro del guión.

Tome el ejemplo de una Tarea que hace algo con todos los archivos que coinciden con "* .txt" en un directorio. Si su script MSBuild se carga en Visual Studio, solo los archivos que existían cuando se inició VS estarán en el Item si usa ItemGroup.

Si usa CreateItem, buscará todos los archivos * .txt cuando se ejecute el destino.

+10

El asker indica que ambos están siendo llamados desde dentro de un objetivo. Según su respuesta, parece que está pensando en los términos anteriores a MSBuild 3.5. (Cuando ItemGroup no se pudo colocar dentro de un objetivo). Si ItemGroup está dentro de un destino, es tan dinámico como si se hubiera declarado a través de CreateItem. (es decir, se evalúa cuando se ejecuta el objetivo.) (Consulte la página 51 de "Dentro del motor de compilación de Microsoft: utilizando MS Build Build Team Foundation" para obtener una referencia (o simplemente pruébelo)). – Vaccano

+0

@Vaccano: Un grupo de artículos es "igual de dinámico" dentro de un objetivo con la excepción mencionada por Johannes Rudolph en un comentario a la respuesta elegida: "CreateItem expandirá los comodines que se le asignan en Incluir mediante una operación de transformación" ... mientras La declaración ItemGroup no lo hará. – CyberMonk

17

CreateItem y CreateProperty están obsoletos en MSBuild 3.5 (aunque siempre seguirán funcionando, por supuesto). Era bastante obvio que necesitábamos la misma sintaxis familiar para ItemGroup y PropertyGroup para trabajar dentro de los objetivos.

Pero ItemGroup dentro de un objetivo tiene algunos poderes especiales adicionales. Puede modificar elementos: por ejemplo, se agregará verdadero a todos los elementos en la lista de Recursos que tienen un metadato llamado Primario con valor de verdadero; solo si no existe ya Copiar metadatos:

<ItemGroup> 
    <Resources Condition=" '%(Primary)' == 'true' "> 
    <Copy Condition=" '%(Copy)' == '' ">true</Copy> 
    </Resources> 
</ItemGroup> 

Otro poder mágico: ahora puede eliminar elementos de una lista.En este ejemplo se va a eliminar todos los elementos de la lista de recursos que han Tipo de metadatos con un valor de mapa de bits:

<ItemGroup> 
    <Resources Condition=" '%(Type)'=='Bitmap' " Remove="@(Resources)"/> 
</ItemGroup> 

Estos poderes mágicos sólo funcionan en el interior en la actualidad, no afuera.

Para obtener todos los detalles de estas cosas, recomiendo encarecidamente el libro de Sayed Hashimi en MSBuild. Se encuentra fácilmente en Amazon.

Dan - equipo de msbuild.

1

Como información adicional para otros que pasan aquí: Build-Engine que contiene una API para construir proyectos de MSBuild no admite agregar ItemGroups de la nueva manera a un objetivo. Aquí tendrá que usar la forma antigua.

Cuestiones relacionadas