2009-06-02 10 views
28

Quelle est la différence entre la création d'un élément à l'intérieur d'une cible comme ceci:CreateItem vs ItemGroup

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

et comme ceci:

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

Quand souhaitez-vous utiliser l'un ou l'autre et pourquoi?

Répondre

27

Dans les versions de MSBuild antérieures à la version 3.5, vous ne pouviez pas définir les propriétés ou les éléments à l'intérieur des cibles (comme dans votre deuxième exemple). Donc, une tâche a été utilisée à la place (CreateItem et CreateProperty)

Si vous utilisez ToolsVersion 3.5, vous n'avez plus besoin d'utiliser CreateItem (bien que vous puissiez le faire si vous préférez). En fin de compte, ils créent tous les deux le même élément, avec la même étendue. L'utilisation de la deuxième syntaxe est plus lisible et la configuration de métadonnées personnalisées est beaucoup plus facile (à mon avis).

REMARQUE: La version 3.5 de MSBuild est installée avec .NET 3.5. Bien que vous devez définir ToolsVersion="3.5" dans la balise Project de votre fichier MSBuild pour utiliser les fonctionnalités 3.5.

Dans le cas où vous vous demandez, j'ai obtenu la plupart de ces informations du livre Inside the Microsoft® Build Engine: Using MSBuild and Team Foundation Build que j'ai vraiment aimé (mais je ne suis pas affilié d'aucune façon).

+0

Merci beaucoup, c'est exactement ce que je voulais savoir! Je vais devoir vérifier ce livre. – Jake

+2

Ouais ce livre est super, j'adore :) :) :) Merci pour la rec. –

+5

J'ai cependant trouvé une grande différence: CreateItem développe les caractères génériques qui lui sont donnés dans Include via une opération de transformation comme alors qu'une déclaration ItemGroup ne l'étend pas . –

7

Je ne pense pas que la réponse acceptée ait défini la différence.

La différence est:

  • ItemGroup est évalué lorsque le script MSBuild est chargé.
  • CreateItem est évaluée lorsque la cible est exécutée

Cela peut conduire à des valeurs différentes de l'élément dans le script. Prenons l'exemple d'une tâche qui fait quelque chose avec tous les fichiers correspondant à "* .txt" dans un répertoire. Si votre script MSBuild est chargé dans Visual Studio, seuls les fichiers qui existaient lors du démarrage de VS seront dans l'élément si vous utilisez ItemGroup.

Si vous utilisez CreateItem, il recherchera tous les fichiers * .txt lors de l'exécution de la cible.

+10

Le demandeur indique que les deux sont appelés depuis l'intérieur d'une cible. D'après votre réponse, il semblerait que vous pensiez à MSBuild 3.5. (Lorsque ItemGroup n'a pas pu être placé à l'intérieur d'une cible). Si ItemGroup est à l'intérieur d'une cible, il est aussi dynamique que s'il avait été déclaré via CreateItem. (c.-à-d. qu'il est évalué lorsque la cible est exécutée.) (Voir la page 51 de «À l'intérieur du moteur de compilation Microsoft: MSBuild et Team Foundation Build» pour une référence (ou essayez-le)). – Vaccano

+0

@Vaccano: Un groupe d'articles est "tout aussi dynamique" à l'intérieur d'une cible à l'exception mentionnée par Johannes Rudolph dans un commentaire à la réponse choisie - "CreateItem développera les caractères génériques qui lui sont donnés dans Inclure via une opération de transformation" ... La déclaration ItemGroup ne le fera pas. – CyberMonk

17

CreateItem et CreateProperty sont obsolètes dans MSBuild 3.5 (bien qu'ils continuent à fonctionner, bien sûr). Il était assez évident que nous avions besoin de la même syntaxe familière pour ItemGroup et PropertyGroup pour travailler à l'intérieur des cibles.

Mais ItemGroup à l'intérieur d'une cible a des pouvoirs supplémentaires spéciaux. Il peut modifier les éléments: par exemple, cela ajoutera true à tous les éléments de la liste des ressources qui ont une métadonnée nommée Primary avec la valeur true; seulement s'il n'y en a pas déjà Copie des métadonnées:

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

Une autre puissance magique: vous pouvez maintenant retirer des éléments d'une liste.Cet exemple supprime tous les éléments de la liste des ressources qui ont des métadonnées de type avec la valeur Bitmap:

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

Ces pouvoirs magiques ne fonctionnent que dans à l'heure actuelle, pas à l'extérieur.

Pour plus de détails sur ce sujet, je recommande fortement le livre de Sayed Hashimi sur MSBuild. Il est facilement trouvé sur Amazon.

Dan - équipe msbuild.

1

Comme une information supplémentaire pour d'autres passant ici: Le Build-Engine qui contient une API pour construire des projets MSBuild ne supporte pas l'ajout de ItemGroups la nouvelle manière à une cible. Ici, vous devrez utiliser la manière démodée.

Questions connexes