4. Aller plus loin avec MsBuild▲
Nous avons exposé jusque là le cas le plus basique d'un fichier de build. Nous allons maintenant aller beaucoup plus loin pour présenter les outils qui seront réellement nécessaires pour automatiser nos tâches quotidiennes.
4-1. S'assurer de la validité du fichier de build▲
Le fichier de build est un fichier XML et doit donc être valide par rapport aux spécifications XML. Il faut donc faire attention aux valeurs que l'on veut spécifier dans les éléments et dans les attributs.
Prenons deux exemples classiques d'erreurs dans un fichier XML :
<!-- Erreur car présence de "&" dans une balise -->
<ElementInvalide>
Valeur 1 &
Valeur 2</ElementInvalide>
<!-- Correction ici par un bloc CDATA -->
<ElementValide>
<![CDATA[
Valeur1 & Valeur2
]]>
</ElementValide>
<!-- Erreur car l'attribut possède un guillemet -->
<ElementAvecAttributInvalide
Attribut
=
"Je possede une ("
)
"/>
<!-- Correction en utilisant le code ASCII -->
<ElementAvecAttributValide Attribut="
Je possede une (%22)
"/>
Pour corriger les erreurs tout en possédant un fichier cohérent, il faudra parfois avoir recours à des astuces, d'autant que certains caractères sont réservés par MsBuild et ne peuvent donc pas être utilisés tels quels. On pourra noter les astuces suivantes :
- Utilisation de blocs CDATA pour protéger un élément
- Utilisation de codes ASCII pour remplacer les caractères réservés par MsBuild
- Utilisation de propriétés lorsque l'on n'est pas capable de protéger correctement ce que l'on veut mettre dans un attribut (dans la source ci-dessus, plutôt que d'utiliser « %22 », on aurait ainsi pu déplacer la valeur dans une propriété, et référencer la propriété. Nous verrons ici comment utiliser les propriétés)
- Utilisation des correspondances HTML de certains caractères
|
|
Pour voir la liste des codes ASCII, on peut aller voir sur
www.asciitable.com ou dans la MSDN.
Plus d'informations dans les annexes : « Table des codes ASCII ».
4-2. Propriétés d'un fichier de build : les Properties et PropertyGroup▲
4-2-1. Définition▲
On peut définir des Properties que l'on pourra utiliser dans notre fichier de projet.
Une property dans un fichier de build est très similaire à une propriété en .NET ou à une variable contenant une valeur simple (string, int, double, ...).
Ces propriétés pourront être créées statiquement - par simple déclaration dans le fichier - ou bien dynamiquement - lors de l'exécution du fichier de build.
4-2-2. Création statique de propriétés▲
Pour créer une property, on peut ajouter dans notre fichier un élément « PropertyGroup » qui peut regrouper plusieurs éléments, chacun d'entre eux étant une nouvelle property. Notez que l'on peut retrouver plusieurs éléments « PropertyGroup » dans un même fichier de projet.
<Project
xmlns
=
"http://schemas.microsoft.com/developer/msbuild/2003"
>
<PropertyGroup>
<MaPropriete1>
Test1</MaPropriete1>
<MaPropriete2>
Test2</MaPropriete2>
</PropertyGroup>
</Project>
Dans le source ci-dessus, nous avons créé
- Une propriété « MaPropriete1 » de valeur « Test1 »
- Une propriété « MaPropriete2 » de valeur « Test2 »
4-2-3. Utilisation de Properties▲
Utiliser une propriété est très simple. Il suffit d'utiliser la syntaxe « $(NomPropriete) ».
<Project
xmlns
=
"http://schemas.microsoft.com/developer/msbuild/2003"
>
<PropertyGroup>
<FileName>
Mastering Regular Expressions</FileName>
<Extension>
pdf</Extension>
<FileNameWithExt>
$(FileName).$(Extension)</FileNameWithExt>
</PropertyGroup>
</Project>
Notez cependant qu'il est important que les propriétés soient définies avant leur appel. Pour cela, il est important de prendre en compte les différences signalées entre « PropertyGroup » et « CreateProperty » détaillées dans le point lié à la « Création dynamique des propriétés ».
4-2-4. Précaution d'emploi : Ordre de déclaration▲
Il faut être vigilant à l'ordre de création des propriétés. En effet la création des propriétés (définies via PropertyGroup) se fait lors de l'initialisation du fichier, mais ce, de haut en bas.
<Project
xmlns
=
"http://schemas.microsoft.com/developer/msbuild/2003"
>
<Target
Name
=
"Target1"
>
<Message
Text
=
"Dans Target 1"
/>
<Message
Text
=
"$(Prop1)"
/>
<Message
Text
=
"$(Prop2)"
/>
</Target>
<PropertyGroup>
<Prop1>
Prop1 : $(PropBase)</Prop1>
<PropBase>
test</PropBase>
<Prop2>
Prop2 : $(PropBase)</Prop2>
</PropertyGroup>
</Project>
Microsoft (R) Build Engine Version 3.5.30729.1
[Microsoft .NET Framework, Version 2.0.50727.3053]
Copyright (C) Microsoft Corporation 2007. All rights reserved.
Build started 9/05/2009 23:16:51.
Project "C:\Temp\build.proj" on node 0 (default targets).
Dans Target 1
Prop1 :
Prop2 : test
Done Building Project "C:\Temp\build.proj" (default targets).
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:00.03
Dans l'exemple ci-dessus, on se rend compte que l'affichage de la propriété Prop1 ne donne pas le résultat escompté, puisque l'on utilise PropBase qui est déclaré après Prop1. L'affichage de Prop2 quand à lui est bien correct.
On se rend compte alors que les propriétés on bien été initialisées avant l'exécution du Target, mais en respectant leur ordre de déclaration, du haut vers le bas.
4-2-5. Création dynamique de Properties▲
4-2-5-1. Définition▲
Il est également possible d'utiliser une tâche CreateProperty pour créer dynamiquement une propriété. Cela permet par exemple d'utiliser des variables qui sont retournées par une autre tâche.
4-2-5-2. Différence entre création statique et dynamique▲
Il faut cependant être très conscient des différences entre création statique et dynamique :
Création statique :
Toutes les variables (propriétés ou items) utilisées pour créer une propriété dans un PropertyGroup doivent exister au moment de la création (et donc il ne peut s'agir du résultat d'une méthode appelée au sein d'un target). En effet toutes les propriétés créées via un PropertyGroup sont initialisées au lancement du fichier
Création dynamique :
Si les propriétés créées dans un PropertyGroup sont visibles et existent à tout moment dans le fichier de Projet, celles créées par la tâche « CreateProperty » n'existent qu'une fois la tâche exécutée. Cependant il n'est pas possible de référencer une propriété si celle-ci est définie après son utilisation (voir l'exemple sur les ordres de déclaration).
4-2-5-3. Syntaxe de la tâche CreateProperty▲
La tâche CreateProperty prend en paramètre d'entrée la valeur de la propriété à créer et nous renvoie la valeur. Il faut alors l'associer au nom de la propriété que l'on veut créer. La syntaxe est similaire pour toutes les tâches ayant des paramètres de sorties (output). Plus synthétiquement, la syntaxe est la suivante :
<CreateProperty
Value
=
"Valeur de la propriété, par exemple: Hello"
>
<Output
TaskParameter
=
"Value"
PropertyName
=
"Le nom de la Property que l'on veut créer"
/>
</CreateProperty>
où Value est le nom de la propriété de la tâche (propriété marquée avec un OutputAttribute) que l'on veut récupérer sous forme de Property. Dans le cas de la tâche CreateProperty, c'est la propriété « Value ».
4-2-5-4. Exemple d'utilisation▲
Dans l'exemple ci-dessous, nous allons créer une propriété « MaProprieteDynamique » (de valeur 'Test3') via la tâche CreateProperty. Cette propriété pourra être utilisée exactement de la même façon que celles créées via un PropertyGroup.
<Project
xmlns
=
"http://schemas.microsoft.com/developer/msbuild/2003"
>
<Target
Name
=
"Target1"
>
<CreateProperty
Value
=
"Test3"
>
<Output
TaskParameter
=
"Value"
PropertyName
=
"MaProprieteDynamique"
/>
</CreateProperty>
<Message
Text
=
"$(MaProprieteDynamique)"
/>
</Target>
</Project>
4-2-6. Changer la valeur d'une propriété▲
Si l'on désire changer la valeur d'une propriété, on peut également utiliser la tâche CreateProperty. Elle ne se contente en effet pas de créer une nouvelle propriété, mais également de mettre à jour la valeur, s'il existe déjà une propriété avec ce nom.
<Project
xmlns
=
"http://schemas.microsoft.com/developer/msbuild/2003"
>
<PropertyGroup>
<MaPropriete>
Valeur initiale</MaPropriete>
</PropertyGroup>
<Target
Name
=
"Target1"
>
<Message
Text
=
"$(MaPropriete)"
/>
<CreateProperty
Value
=
"Nouvelle valeur"
>
<Output
TaskParameter
=
"Value"
PropertyName
=
"MaPropriete"
/>
</CreateProperty>
<Message
Text
=
"$(MaPropriete)"
/>
</Target>
</Project>
Microsoft (R) Build Engine Version 3.5.30729.1
[Microsoft .NET Framework, Version 2.0.50727.3053]
Copyright (C) Microsoft Corporation 2007. All rights reserved.
Build started 9/05/2009 23:18:54.
Project "C:\Temp\build.proj" on node 0 (default targets).
Valeur initiale
Nouvelle valeur
Done Building Project "C:\Temp\build.proj" (default targets).
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:00.07
4-2-7. Différer la création d'un PropertyGroup▲
Nous avons vu dans la section « Création statique de propriétés » que les « PropertyGroup » étaient initialisés lors du lancement du fichier.
Il est cependant possible de différer leur initialisation de façon à ce que les PropertyGroup se comportent comme des propriétés dynamiques. Pour cela, il suffit de les placer au sein d'un Target.
Pour illustrer cet exemple, nous utilisons l'attribut DependsOnTarget. Nous le détaillerons dans la section « Contrôler l'ordre d'exécution des Targets ».
Supposons seulement à ce stade que le Target SetProprietes sera lancé avant le Target Main.
<Project
DefaultTargets
=
"Main"
xmlns
=
"http://schemas.microsoft.com/developer/msbuild/2003"
>
<Target
Name
=
"Main"
DependsOnTargets
=
"SetProprietes"
>
<Message
Text
=
"Ma Propriete Dynamique: $(MaProprieteDynamique)"
/>
</Target>
<Target
Name
=
"SetProprietes"
>
<!-- Ici la propriété n'a pas encore été créée -->
<Message
Text
=
"Ma Propriete Dynamique: $(MaProprieteDynamique)"
/>
<!-- Là on va créer dynamiquement la propriété -->
<PropertyGroup>
<MaProprieteDynamique>
Valeur</MaProprieteDynamique>
</PropertyGroup>
<!-- La propriété existe donc ici -->
<Message
Text
=
"Ma Propriete Dynamique: $(MaProprieteDynamique)"
/>
</Target>
</Project>
Microsoft (R) Build Engine Version 3.5.30729.1
[Microsoft .NET Framework, Version 2.0.50727.3053]
Copyright (C) Microsoft Corporation 2007. All rights reserved.
Build started 23/04/2009 8:15:04.
Project "D:\Fichiers de build\Création de propriétés via PropertyGroup.proj" on node 0 (default targets).
Ma Propriete Dynamique:
Ma Propriete Dynamique: Valeur
Main:
Ma Propriete Dynamique: Valeur
Done Building Project "D:\Fichiers de build\Création de propriétés via PropertyGroup.proj" (default targets).
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:00.03
Dans l'exemple ci-dessus, on remarque que le PropertyGroup n'a pas été initialisé lors du démarrage du fichier, mais bien lorsque le flot d'exécution est passé sur le PropertyGroup.
Cette syntaxe est en fait une version simplifiée de la tâche CreateProperty.
4-3. Listes d'un fichier de build : les Items et ItemGroup▲
4-3-1. Définition▲
Outre les propriétés, on peut également utiliser des Items qui sont une structure beaucoup plus complexe. On peut les comparer en fait à une collection d'objets non typés, chaque objet étant typiquement un type simple (int, string, ...) mais auquel on peut adjoindre des propriétés (appelées MetaData).
Les MetaData sont en fait des propriétés d'une des valeurs de l'Item. Toutes les valeurs d'un même
Item ne doivent donc pas forcément posséder les mêmes MetaData.
Nous verrons plus clairement ce cas dans l'exemple proposé dans la partie traitant de la
« création statique des items ».
4-3-2. Création statique d'Items▲
Comme les PropertyGroup pour les propriétés, on retrouve des ItemGroup pour la création d'Items. La syntaxe est cependant légèrement différente de par la définition possible des MetaData.
<Project
xmlns
=
"http://schemas.microsoft.com/developer/msbuild/2003"
>
<ItemGroup>
<Item1
Include
=
"Item avec Metadata"
<Display>
True</Display>
<AutreMetaData>
Valeur</AutreMetaData>
</Item1>
<Item2
Include
=
"Item sans Metadata"
/>
<Item3
Include
=
"Val1;Val2"
/>
</ItemGroup>
</Project>
Dans l'exemple ci-dessus, on a créé
- Un item « Item1 » possédant une valeur « Item avec Metadata » lui-même composé de deux metadata
- « Display » de valeur « True »
- « AutreMetaData » de valeur « Valeur »
- Un item « Item2 » possédant une valeur : « Item sans Metadata »
- Un item « Item3 » possédant deux valeurs : « Val1 » et « Val2 »
Si l'on veut déclarer plusieurs valeurs dans un même item, on peut soit utiliser la syntaxe de « Item3 » ci-dessus, soit déclarer deux attributs XML de cette façon :
<Project
xmlns
=
"http://schemas.microsoft.com/developer/msbuild/2003"
>
<ItemGroup>
<Item1
Include
=
"Val1"
<Display>
True</Display>
</Item1>
<Item1
Include
=
"Val2"
<AutreMetaData>
Valeur</AutreMetaData>
</Item1>
</ItemGroup>
</Project>
C'est de cette façon que l'on peut spécifier des metadata différentes pour certaines valeurs d'un même item.
4-3-3. Utilisation d'Items▲
Pour utiliser un item, il faut utiliser la syntaxe « @(NomItem) ».
Pour accéder à une metadata particulière d'un Item, il suffit d'utiliser la syntaxe « %(NomItem.NomMetaData) » ou « %(NomMetaData) ». Cette deuxième syntaxe pourrait cependant échouer à la moindre ambiguïté et est d'ailleurs la plupart du temps à déconseiller en termes de lisibilité.
<Project
xmlns
=
"http://schemas.microsoft.com/developer/msbuild/2003"
>
<ItemGroup>
<Item1
Include
=
"Val1;Val2"
/>
<Item2
Include
=
"Test avec Display"
>
<Display>
True</Display>
</Item2>
<Item2
Include
=
"Test sans Display"
>
<Display>
False</Display>
</Item2>
</ItemGroup>
<Target
Name
=
"Target1"
>
<Message
Text
=
"Item1 = @(Item1)"
/>
<Message
Text
=
"Item2 = @(Item2)"
/>
<Message
Text
=
"Item2.Display = %(Item2.Display)"
/>
</Target>
</Project>
Microsoft (R) Build Engine Version 3.5.30729.1
[Microsoft .NET Framework, Version 2.0.50727.3053]
Copyright (C) Microsoft Corporation 2007. All rights reserved.
Build started 9/05/2009 23:20:22.
Project "C:\Temp\build.proj" on node 0 (default targets).
Item1 = Val1;Val2
Item2 = Test avec Display;Test sans Display
Item2.Display = True
Item2.Display = False
Done Building Project "C:\Temp\build.proj" (default targets).
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:00.01
Comme on pouvait s'y attendre, demander la valeur d'Item2 va nous afficher la liste de ses différentes valeurs concaténées par un « ; ».
En demandant la valeur d'une metadata d'Item2, il y aura autant de lignes générées que de valeurs de l'item possédant la metadata demandée.
4-3-4. Création dynamique d'Items▲
4-3-4-1. Syntaxe et exemple▲
Il est également possible d'utiliser une tâche CreateItem pour créer dynamiquement un item.
La syntaxe sera très proche de celle de la tâche CreateProperty. Le grand avantage est que cela nous permet d'utiliser des conditions de création.
<Project
xmlns
=
"http://schemas.microsoft.com/developer/msbuild/2003"
>
<PropertyGroup>
<MyValue>
Hello</MyValue>
</PropertyGroup>
<ItemGroup>
<Item2
Include
=
"Test avec Display"
>
<Display>
True</Display>
</Item2>
<Item2
Include
=
"Test sans Display"
>
<Display>
False</Display>
</Item2>
</ItemGroup>
<Target
Name
=
"Target1"
>
<CreateItem
Include
=
"@(Item2)"
Condition
=
"'%(Display)'=='true'"
AdditionalMetadata
=
"MonDisplay=%(Display);AutreMetaData=$(MyValue)"
>
<Output
TaskParameter
=
"Include"
ItemName
=
"MonNouvelItemAvecMetadata"
/>
</CreateItem>
<Message
Text
=
"@(MonNouvelItemAvecMetadata)"
/>
<Message
Text
=
"%(MonNouvelItemAvecMetadata.MonDisplay)"
/>
<Message
Text
=
"%(MonNouvelItemAvecMetadata.AutreMetaData)"
/>
</Target>
</Project>
Microsoft (R) Build Engine Version 3.5.30729.1
[Microsoft .NET Framework, Version 2.0.50727.3053]
Copyright (C) Microsoft Corporation 2007. All rights reserved.
Build started 9/05/2009 23:21:26.
Project "C:\Temp\build.proj" on node 0 (default targets).
Test avec Display
True
Hello
Done Building Project "C:\Temp\build.proj" (default targets).
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:00.04
Dans l'exemple ci-dessus, on créé dynamiquement un Item en spécifiant que
- On veut le créer à partir de l'Item « Item2 » (qui possède deux valeurs : « Test avec Display » et « Test sans Display »)
- En filtrant sur tous les Items « Item2 » pour lesquels on a une MetaData « Display » de valeur « true »
- On veut ajouter deux nouvelles MetaData à toutes les valeurs de l'item que l'on veut créer, le premier étant simplement la valeur de la MetaData « Display » de l'Item inclus, et l'autre provenant d'une propriété
Notez que pour avoir plus d'informations sur les conditions possibles, vous pouvez vous référez à la bibliographie sur les conditions utilisables.
Notez enfin que ces conditions sont également utilisables sur un ItemGroup et un PropertyGroup au complet afin d'éviter la création de certaines variables qui pourraient être inutiles.
4-3-4-2. Cas particulier lors de l'utilisation de metadata▲
Notez que dans les AdditionalMetaData, on peut utiliser des Properties, des MetaData de l'Item que l'on inclut, ou des MetaData d'autres items. Dans ce dernier cas, s'il y a plusieurs valeurs de cet autre item possédant la MetaData souhaitée, chaque valeur de l'Item généré sera clonée afin que chaque valeur puisse posséder toutes les MetaData possibles. Voyons cela dans l'exemple ci-dessous :
<Project
xmlns
=
"http://schemas.microsoft.com/developer/msbuild/2003"
>
<ItemGroup>
<Item1
Include
=
"Test avec Display"
>
<Display>
True</Display>
</Item1>
<Item1
Include
=
"Test sans Display"
>
<Display>
False</Display>
</Item1>
</ItemGroup>
<Target
Name
=
"Target2"
>
<CreateItem
Include
=
"Valeur"
AdditionalMetadata
=
"Display=%(Item1.Display)"
>
<Output
TaskParameter
=
"Include"
ItemName
=
"MonNouvelItem"
/>
</CreateItem>
<Message
Text
=
"MonNouvelItem = @(MonNouvelItem)"
/>
<Message
Text
=
"MonNouvelItem.Display = %(MonNouvelItem.Display)"
/>
</Target>
</Project>
Microsoft (R) Build Engine Version 3.5.30729.1
[Microsoft .NET Framework, Version 2.0.50727.3053]
Copyright (C) Microsoft Corporation 2007. All rights reserved.
Build started 9/05/2009 23:22:28.
Project "C:\Temp\build.proj" on node 0 (default targets).
MonNouvelItem = Valeur;Valeur
MonNouvelItem.Display = True
MonNouvelItem.Display = False
Done Building Project "C:\Temp\build.proj" (default targets).
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:00.04
Ici, nous avons donc créé un item en lui assignant une seule valeur (« Valeur »), et en lui assignant comme nouvelle metadata la valeur de la metadata « Display » de l'item Item1. Comme Item1 possède plusieurs éléments, et que ces éléments n'ont pas tous la même valeur pour la metadata « Display », alors le nouvel item contiendra deux éléments.
Si tous les éléments d'Item1 possédaient la même valeur pour « Display », alors ce clonage n'aurait pas lieu.
<Project
xmlns
=
"http://schemas.microsoft.com/developer/msbuild/2003"
>
<ItemGroup>
<Item1
Include
=
"Test avec Display"
>
<Display>
True</Display>
</Item1>
<Item1
Include
=
"Test également avec Display"
>
<Display>
True</Display>
</Item1>
</ItemGroup>
<Target
Name
=
"Target1"
>
<CreateItem
Include
=
"Valeur"
AdditionalMetadata
=
"Display=%(Item1.Display)"
>
<Output
TaskParameter
=
"Include"
ItemName
=
"MonNouvelItem"
/>
</CreateItem>
<Message
Text
=
"MonNouvelItem = @(MonNouvelItem)"
/>
<Message
Text
=
"MonNouvelItem.Display = %(MonNouvelItem.Display)"
/>
</Target>
</Project>
Microsoft (R) Build Engine Version 3.5.30729.1
[Microsoft .NET Framework, Version 2.0.50727.3053]
Copyright (C) Microsoft Corporation 2007. All rights reserved.
Build started 9/05/2009 23:24:20.
Project "C:\Temp\build.proj" on node 0 (default targets).
MonNouvelItem = Valeur
MonNouvelItem.Display = True
Done Building Project "C:\Temp\build.proj" (default targets).
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:00.07
4-3-5. Précautions lors de l'utilisation d'Items dans des tâches▲
Comme nous l'avons vu dans les exemples précédents, il faut bien prendre en compte le fait que les Items sont des collections de valeurs, et donc deux items différents pourraient avoir un nombre de valeurs différent et des metadata différentes. De même, deux valeurs d'un même item pourraient également avoir des metadata différentes. Par conséquent, il se peut que les tâches qui utilisent des items aient des comportements particuliers.
En effet, il est impossible de joindre dans une même collection des éléments différents de façon cohérente. MsBuild va donc automatiquement scinder les appels aux tâches lorsque plusieurs Items sont utilisés.
<Project
DefaultTargets
=
"Target1"
xmlns
=
"http://schemas.microsoft.com/developer/msbuild/2003"
>
<ItemGroup>
<Item1
Include
=
"ValeurItem1"
>
<Data>
La MetaData de l'Item1</Data>
</Item1>
<AutreItem
Include
=
"ValeurAutreItem"
>
<Display>
True</Display>
</AutreItem>
</ItemGroup>
<Target
Name
=
"Target1"
>
<Message
Text
=
"Item1: @(Item1) - Autre Item: @(AutreItem)"
/>
<Message
Text
=
"Item1: %(Item1.Data) - Autre Item: %(AutreItem.Display)"
/>
</Target>
</Project>
Microsoft (R) Build Engine Version 3.5.30729.1
[Microsoft .NET Framework, Version 2.0.50727.3053]
Copyright (C) Microsoft Corporation 2007. All rights reserved.
Build started 9/05/2009 23:25:23.
Project "C:\Temp\build.proj" on node 0 (default targets).
Item1: ValeurItem1 - Autre Item: ValeurAutreItem
Item1: La MetaData de l'Item1 - Autre Item:
Item1: - Autre Item: True
Done Building Project "C:\Temp\build.proj" (default targets).
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:00.03
De même si l'on complète l'exemple en ajoutant une nouvelle valeur pour l'item 1, le résultat aura une ligne supplémentaire.
<Project
DefaultTargets
=
"Target1"
xmlns
=
"http://schemas.microsoft.com/developer/msbuild/2003"
>
<ItemGroup>
<Item1
Include
=
"ValeurItem1"
>
<Data>
La MetaData de Item1</Data>
</Item1>
<Item1
Include
=
"AutreValeurItem1"
>
<Data>
La MetaData de l'autre Item1</Data>
</Item1>
<AutreItem
Include
=
"ValeurAutreItem"
>
<Display>
True</Display>
</AutreItem>
</ItemGroup>
<Target
Name
=
"Target1"
>
<Message
Text
=
"Item1: @(Item1) - Autre Item: @(AutreItem)"
/>
<Message
Text
=
"Item1: %(Item1.Data) - Autre Item: %(AutreItem.Display)"
/>
</Target>
</Project>
Microsoft (R) Build Engine Version 3.5.30729.1
[Microsoft .NET Framework, Version 2.0.50727.3053]
Copyright (C) Microsoft Corporation 2007. All rights reserved.
Build started 9/05/2009 23:26:15.
Project "C:\Temp\build.proj" on node 0 (default targets).
Item1: ValeurItem1;AutreValeurItem1 - Autre Item: ValeurAutreItem
Item1: La MetaData de Item1 - Autre Item:
Item1: La MetaData de l'autre Item1 - Autre Item:
Item1: - Autre Item: True
Done Building Project "C:\Temp\build.proj" (default targets).
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:00.03
Pour réellement concaténer ces valeurs, il faudrait passer par la création d'items ou de propriétés intermédiaires.
4-3-6. Différer la création d'un ItemGroup▲
De même que pour les PropertyGroup, il est possible de différer la création d'un ItemGroup de façon à ce que celui-ci ne soit pas initialisé au démarrage du fichier. Il suffit également de déplacer l'ItemGroup dans le target, à l'emplacement du flot d'exécution souhaité.
Pour illustrer cet exemple, nous utilisons l'attribut DependsOnTarget. Nous le détaillerons
dans la section « Contrôler l'ordre d'exécution des
Targets ».
Supposons seulement à ce stade que le Target SetProprietes sera lancé avant le
Target Main.
<Project
DefaultTargets
=
"Main"
xmlns
=
"http://schemas.microsoft.com/developer/msbuild/2003"
>
<Target
Name
=
"Main"
DependsOnTargets
=
"SetItem"
>
<Message
Text
=
"Mon Item Dynamique: @(MonItemDynamique)"
/>
<Message
Text
=
"Mon Item MetaData : %(MonItemDynamique.MetaData)"
/>
</Target>
<Target
Name
=
"SetItem"
>
<!-- Ici l'item n'a pas encore été créée -->
<Message
Text
=
"Mon Item Dynamique: @(MonItemDynamique)"
/>
<Message
Text
=
"Mon Item MetaData : %(MonItemDynamique.MetaData)"
/>
<!-- Là on va créer dynamiquement la propriété -->
<ItemGroup>
<MonItemDynamique
Include
=
"Valeur"
>
<MetaData>
Valeur MetaData</MetaData>
</MonItemDynamique>
</ItemGroup>
<!-- L'item existe donc ici -->
<Message
Text
=
"Mon Item Dynamique: @(MonItemDynamique)"
/>
<Message
Text
=
"Mon Item MetaData : %(MonItemDynamique.MetaData)"
/>
</Target>
</Project>
Microsoft (R) Build Engine Version 3.5.30729.1
[Microsoft .NET Framework, Version 2.0.50727.3053]
Copyright (C) Microsoft Corporation 2007. All rights reserved.
Build started 23/04/2009 8:26:11.
Project "D:\Fichiers de build\Création d'items via ItemGroup.proj" on node 0 (default targets).
Mon Item Dynamique:
Mon Item MetaData :
Mon Item Dynamique: Valeur
Mon Item MetaData : Valeur MetaData
Main:
Mon Item Dynamique: Valeur
Mon Item MetaData : Valeur MetaData
Done Building Project "D:\Fichiers de build\Création d'items via ItemGroup.proj" (default targets).
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:00.01
4-4. Exécuter un fichier de build▲
Nous avions vu dans la section « Exécuter un fichier de build » la façon la plus simple pour exécuter un fichier. Il y a cependant d'autres façons de le faire, de façon à surcharger le comportement par défaut.
4-4-1. Exécution par défaut▲
Pour rappel, l'exécution la plus simple requiert uniquement le nom du fichier « .proj » à lancer. Dans ce cas, le target par défaut sera exécuté.
Le target par défaut sera déterminé comme suit :
- Si un seul target dans le fichier, c'est celui-là qui sera lancé
- Si plusieurs targets
- Si l'un d'entre eux est marqué comme par défaut, alors c'est celui-là qui sera lancé (nous verrons plus d'informations sur la notion de target par défaut dans la section « Contrôler l'ordre d'exécution des Targets »)
- Sinon, c'est le premier target présent dans le fichier qui sera lancé
MsBuild BuildA.proj
4-4-2. Surcharge du target à exécuter▲
On peut cependant utiliser l'option « /target:NomTarget » ou « /t:NomTarget » pour spécifier un autre target de démarrage. Dans ce cas, le target par défaut sera ignoré.
Pour en spécifier plusieurs, il faut les séparer par un « ; » ou utiliser plusieurs options « /t ».
MsBuild /t:Rebuild BuildA.proj
4-4-3. Surcharge d'une propriété▲
On a également la possibilité de surcharger la valeur des propriétés statiques - c'est à dire celles créées dans un PropertyGroup - lors de l'exécution. Pour cela, il suffit d'utiliser l'option « /property » (ou sa forme abrégée « /p ») avec la syntaxe « /property:NomPropriete=ValeurPropriete » ou « /p:NomPropriete=ValeurPropriete ».
De nouveau pour surcharger plusieurs propriétés, il faut soit les séparer par un « ; » soit utiliser plusieurs options « /p ».
Par exemple, avec le fichier de projet « Test.proj » suivant :
<Project
xmlns
=
"http://schemas.microsoft.com/developer/msbuild/2003"
>
<PropertyGroup>
<Message>
Hello</Message>
</PropertyGroup>
<Target
Name
=
"Target1"
>
<Message
Text
=
"$(Message)"
/>
</Target>
</Project>
On peut surcharger la valeur de « Message » de la manière suivante :
REM. Va afficher "Hello"
MsBuild Test.proj
REM. Va afficher "Bonjour"
MsBuild /property:Message=Bonjour Test.proj
MsBuild /p:Message=Bonjour Test.proj
Notez cependant qu'il n'est pas possible de surcharger d'une manière similaire la valeur ou une metadata d'un item statique.
4-4-4. Surcharge de la verbosité d'exécution▲
Il est également possible de contrôler le niveau de verbosité lors de l'exécution pour avoir plus ou moins de détail et de commentaires.
On peut utiliser pour cela l'option « /verbosity » ou sa forme abrégée « /v ». Les différentes valeurs possibles correspondent en fait aux valeurs (en minuscules) de l'énumération Microsoft.Build.Framework.LoggerVerbosity :
- quiet (ou q)
- minimal (ou m)
- normal (ou n)
- detailed (ou d)
- diagnostic (ou diag)
Pour plus d'informations sur les différences entre ces différentes valeurs, vous pouvez vous reportez aux liens données dans la bibliographie sur les différents niveaux de verbosité.
Il est cependant important de connaître cette possibilité, puisqu'il peut y avoir un facteur de dix entre la quantité d'information archivée en mode diagnostique et en mode normal.
MsBuild /verbosity:detailed Test.proj
MsBuild /v:detailed Test.proj
4-4-5. Omission du nom du fichier▲
Notez enfin que MsBuild exécutera en fait le fichier de projet qu'il trouve dans le répertoire courant. Par conséquent, si votre répertoire courant ne comporte qu'un seul fichier de projet, vous pouvez même l'omettre dans la ligne de commande.
4-5. Référencer une tâche du framework 3.5▲
Par défaut, lorsque l'on exécute MsBuild, il référence déjà un certain nombre de tâches, telle que les tâches Message, CreateProperty et CreateItem. Il référence en fait toutes les tâches qui sont déclarées dans la DLL Microsoft.Build.Task.dll.
Avec l'arrivée du framework 3.5, Microsoft a ajouté de nouvelles tâches et a complété des tâches existantes. Toutes ces « nouvelles » tâches ont été ajoutées dans la DLL Microsoft.Build.Task.v3.5.dll.
Si l'on veut utiliser un de ces tâches définies dans une autre DLL que celle référencée par défaut, on peut utiliser la commande UsingTask.
Notez bien que l'on référence une simple tâche présente dans une DLL, et non toute la DLL. Par conséquent, si l'on veut utiliser trois tâches de la même DLL, il est impératif de déclarer trois UsingTask différents.
La commande UsingTask nous offre deux paramètres mutuellement exclusifs que sont AssemblyName et AssemblyPath. Le premier nous permet de donner le nom de l'assembly - à condition que celle-ci soit définie dans la GAC. Le second nous permet de spécifier le chemin complet vers une DLL.
<Project
xmlns
=
"http://schemas.microsoft.com/developer/msbuild/2003"
>
<UsingTask
TaskName
=
"GetFrameworkPath"
AssemblyName
=
"Microsoft.Build.Tasks.v3.5"
/>
<Target
Name
=
"Target1"
>
<GetFrameworkPath>
<Output
TaskParameter
=
"FrameworkVersion35Path"
PropertyName
=
"MsBuildPath"
/>
</GetFrameworkPath>
<Message
Text
=
"$(MsBuildPath)"
/>
</Target>
</Project>
Microsoft (R) Build Engine Version 3.5.30729.1
[Microsoft .NET Framework, Version 2.0.50727.3053]
Copyright (C) Microsoft Corporation 2007. All rights reserved.
Build started 27/01/2009 7:55:48.
Project "D:\Fichiers de build\Utilisation de UsingTask.proj" on node 0 (default targets).
C:\WINDOWS\Microsoft.NET\Framework\v3.5
Done Building Project "D:\Fichiers de build\Utilisation de UsingTask.proj" (default targets).
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:00.03
Si nous avions omis la commande UsingTask, alors MsBuild aurait simplement utilisé la version « 2.0 » de la tâche et nous aurions reçu l'erreur suivante :
The "FrameworkVersion35Path" parameter is not supported by the "GetFrameworkPath" task. Verify the parameter exists on the task, and it is a gettable public instance property.
Il est donc crucial de bien regarder dans quelle DLL (ie dans quelle version du framework) la tâche que vous voulez utiliser a été déclarée. La MSDN nous fournit cette information via les éléments Assembly et Version Information.
Une tâche existant à la fois dans le framework 2.0 et 3.5 (comme la tâche GetFrameworkPath
par exemple) n'apparaitra qu'une seule fois dans la MSDN.
Ainsi lorsque l'on visualisera la tâche elle-même, la MSDN nous indiquera qu'elle existe dans la
DLL Microsoft.Build.Task.dll. Mais c'est lorsque l'on regardera la propriété FrameworkVersion35Path
que l'on verra qu'elle appartient à la DLL Microsoft.Build.Task.v3.5.dll
4-6. Plus loin avec les Targets▲
4-6-1. Contrôler l'ordre d'exécution des Targets▲
4-6-1-1. Définition▲
Bien que l'on puisse choisir lors de l'exécution le « Target » à exécuter (voir la section « Exécuter un fichier de build »), il est possible de contrôler dans le fichier l'ordre d'exécution via les attributs DefaultTargets, InitialTargets et DependsOnTargets.
Ces différents attributs sont assez explicites :
- DefaultTargets spécifie le(s) target(s) qui sera exécuté si aucun target n'est spécifié lors de l'exécution en ligne de commande (cas de la syntaxe proposé dans la section « Exécuter un fichier de build » - version simple)
- InitalTargets spécifie le(s) target(s) qui sera lancé au démarrage, avant tout autre target
- DependsOnTargets spécifie le(s) target(s) à lancer avant l'exécution d'un autre target
Si les deux premiers sont donc liés au fichier de projet, le dernier est lié à un target.
4-6-1-2. Exemple▲
<Project
DefaultTargets
=
"Target1"
InitialTargets
=
"Init"
xmlns
=
"http://schemas.microsoft.com/developer/msbuild/2003"
>
<Target
Name
=
"PreTarget1"
/>
<Target
Name
=
"PreTarget2"
/>
<Target
Name
=
"Init"
/>
<Target
Name
=
"Target1"
DependsOnTargets
=
"PreTarget1;PreTarget2"
/>
</Project>
Dans l'exemple ci-dessus, il est spécifié que :
- Si aucun autre target n'est spécifié lors de l'exécution, le target exécuté sera « Target1 » (DefaultTargets)
- Quel que soit le target démarré lors de l'exécution, le target « Init » sera lancé en premier (InitialTargets)
- Avant de lancer le target « Target1 », les deux targets « PreTarget1 » et « PreTarget2 » seront exécutés - et ce dans cet ordre - (« Target1 » DependsOnTargets « PreTarget1 » et « PreTarget2 »
Comme présenté en exemple dans l'attribut DependsOnTargets, on peut préciser plusieurs Target en les séparant par des « ; ». Ceci est également vrai pour les attributs DefaultTargets et InitialTargets.
4-6-1-3. Cas des dépendances multiples▲
Notez cependant que dans le cas de l'exemple ci-dessous, l'exécution du Target1 nécessite l'exécution des « PreTarget1 » et « PreTarget2 ». De plus « PreTarget2 » nécessite également l'exécution de « PreTarget1 ».
Dans ce cas, le « PreTarget1 » ne sera exécuté qu'une et une seule fois.
<Project
DefaultTargets
=
"Target1"
xmlns
=
"http://schemas.microsoft.com/developer/msbuild/2003"
>
<Target
Name
=
"PreTarget1"
>
<Message
Text
=
"Dans PreTarget1"
/>
</Target>
<Target
Name
=
"PreTarget2"
DependsOnTargets
=
"PreTarget1"
>
<Message
Text
=
"Dans PreTarget2"
/>
</Target>
<Target
Name
=
"Target1"
DependsOnTargets
=
"PreTarget1;PreTarget2"
>
<Message
Text
=
"Dans Target1"
/>
</Target>
</Project>
Microsoft (R) Build Engine Version 3.5.30729.1
[Microsoft .NET Framework, Version 2.0.50727.3053]
Copyright (C) Microsoft Corporation 2007. All rights reserved.
Build started 9/05/2009 23:35:48.
Project "C:\Temp\build.proj" on node 0 (default targets).
Dans PreTarget1
PreTarget2:
Dans PreTarget2
Target1:
Dans Target1
Done Building Project "C:\Temp\build.proj" (default targets).
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:00.10
4-6-2. Appeler explicitement un Target▲
Il est possible d'appeler explicitement un target au sein d'un autre target. Pour cela, deux tâches différentes existent : CallTarget et MsBuild.
4-6-2-1. Appeler un target via CallTarget▲
Cette tâche n'est utilisable que si les targets cibles et source se trouvent dans le même fichier de build, sinon c'est vers la tâche MsBuild qu'il faut se tourner.
<Project
xmlns
=
"http://schemas.microsoft.com/developer/msbuild/2003"
>
<Target
Name
=
"Target1"
>
<Message
Text
=
"Dans Target 1"
/>
<CallTarget
Targets
=
"Target2"
/>
</Target>
<Target
Name
=
"Target2"
>
<Message
Text
=
"Dans Target 2"
/>
</Target>
</Project>
Microsoft (R) Build Engine Version 3.5.30729.1
[Microsoft .NET Framework, Version 2.0.50727.3053]
Copyright (C) Microsoft Corporation 2007. All rights reserved.
Build started 9/05/2009 23:37:04.
Project "C:\Temp\build.proj" on node 0 (default targets).
Dans Target 1
Target2:
Dans Target 2
Done Building Project "C:\Temp\build.proj" (default targets).
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:00.03
Notez cependant que le target ne pourra être exécuté qu'une seule fois, de la même façon que pour les dépendances entre les targets décrites dans la partie « Cas des dépendances multiples ».
Ainsi le résultat sera inchangé si on a le fichier de build suivant:
<Project
xmlns
=
"http://schemas.microsoft.com/developer/msbuild/2003"
>
<Target
Name
=
"Target1"
>
<Message
Text
=
"Dans Target 1"
/>
<CallTarget
Targets
=
"Target2"
/>
<CallTarget
Targets
=
"Target2"
/>
</Target>
<Target
Name
=
"Target2"
>
<Message
Text
=
"Dans Target 2"
/>
</Target>
</Project>
Microsoft (R) Build Engine Version 3.5.30729.1
[Microsoft .NET Framework, Version 2.0.50727.3053]
Copyright (C) Microsoft Corporation 2007. All rights reserved.
Build started 9/05/2009 23:38:02.
Project "C:\Temp\build.proj" on node 0 (default targets).
Dans Target 1
Target2:
Dans Target 2
Done Building Project "C:\Temp\build.proj" (default targets).
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:00.03
Notez enfin qu'avec la tâche CallTarget, les targets sources et cibles partageront les même propriétés, qu'elles aient été créées statiquement ou dynamiquement. Il ne sera donc pas possible de donner une autre valeur à une propriété le temps de l'appel à ce target, comme si l'on passait un paramètre à une méthode. (5)
4-6-2-2. Appeler un target via MsBuild▲
Nous avons également à notre disposition la tâche MsBuild. Elle possède l'énorme avantage de nous permettre de passer des paramètres (ie des propriétés) au target cible, ainsi que d'appeler plusieurs fois le même target. Par conséquent, nous pouvons utiliser cette tâche afin d'utiliser des targets comme s'il s'agissait de « méthodes utilitaires ».
Pour appeler la tâche, nous devons spécifier le fichier de projet que l'on veut exécuter. Pour cela, nous pouvons :
- Soit donner le chemin et le nom du fichier à exécuter
- Soit utiliser la propriété $(MsBuildProjectFile) qui nous permet d'exécuter un target situé dans le fichier de projet courant.
<Project
xmlns
=
"http://schemas.microsoft.com/developer/msbuild/2003"
>
<Target
Name
=
"Target1"
>
<Message
Text
=
"Dans Target1"
/>
<MSBuild
Targets
=
"Target2"
Projects
=
"$(MSBuildProjectFile)"
/>
</Target>
<Target
Name
=
"Target2"
>
<Message
Text
=
"Dans Target2"
/>
</Target>
</Project>
Microsoft (R) Build Engine Version 3.5.30729.1
[Microsoft .NET Framework, Version 2.0.50727.3053]
Copyright (C) Microsoft Corporation 2007. All rights reserved.
Build started 9/01/2009 8:59:47.
Project "D:\Appel de target via MsBuild.proj" on node 0 (default targets).
Dans Target1
Project "D:\Appel de target via MsBuild.proj" (1) is building "D:\Appel de target via MsBuild.proj" (1:2) on node 0 (Target2 target(s)).
Dans Target2
Done Building Project "D:\Appel de target via MsBuild.proj" (Target2 target(s)).
Done Building Project "D:\Appel de target via MsBuild.proj" (default targets).
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:00.04
Comme on peut le voir dans l'exemple, c'est le même process MsBuild.exe qui va exécuter les deux targets.
Cette méthode nous permet d'exécuter plusieurs fois le même target, à quelques limitations près. Il faut savoir en effet que MsBuild.exe stocke la liste de tous les targets exécutés et interdit qu'un target exécuté ne soit ré-exécuté une seconde fois.
Ainsi pour qu'un target puisse être lancé plusieurs fois, il faut impérativement qu'ils soient considérés comme différents. Pour cela, on peut se permettre de passer des propriétés différentes en entrée. Nous donnerons un exemple de ce cas dans la partie « Passer des paramètres à un Target ».
4-6-2-3. Choisir CallTarget ou MsBuild▲
Reprenons sous la forme d'un tableau les principales différences entre les deux tâches pour savoir laquelle choisir selon les cas.
CallTarget | MsBuild | |
---|---|---|
Exécuter un target se trouvant dans le même fichier | ||
Exécuter un target se trouvant dans un autre fichier | ||
Partager toutes les propriétés existantes entre le target source et cible | (6) | |
Passer des propriétés au target cible | (7) | |
Appeler plusieurs fois le même target | ||
Récupérer des propriétés en sortie de l'exécution |
4-6-2-4. La tâche Exec▲
Une dernière possibilité existe également : la tâche Exec qui permet d'exécuter une ligne de commande. On va alors construire la ligne de commande comme décrit dans la section « Exécuter un fichier de build ».
<GetFrameworkPath>
<Output
TaskParameter
=
"Path"
PropertyName
=
"MsBuildPath"
/>
</GetFrameworkPath>
<Exec
Command
=
"$(MsBuildPath)\msbuild %22$(MSBuildProjectFile)%22 /t:Target2"
/>
Notez qu'ici on utilise la propriété Path de la tâche GetFrameworkPath. Selon nos besoins, il pourra être important d'utiliser les propriétés FrameworkVersion20Path ou FrameworkVersion35Path. Pour cela, on pourra alors utiliser la version 3.5 de la tâche GetFrameworkPath en se basant sur l'exemple fourni dans la section « Référencer une tâche du framework 3.5 ».
4-6-3. Passer des paramètres à un Target▲
4-6-3-1. Paramètres d'entrée▲
Comme nous l'avons vu, il n'est possible de passer des paramètres d'entrée à une tâche que si on l'appelle via les tâches Exec ou via MsBuild.
Pour la tâche Exec, il suffit bien sûr d'utiliser la même syntaxe que lorsque l'on utilise MsBuild en ligne de commande, soit via les options « /property » ou « /p » tel que décrit dans la section « Surcharge d'une propriété ».
En ce qui concerne la tâche MsBuild, une propriété spécifique peut être utilisée à cet effet.
<Project
xmlns
=
"http://schemas.microsoft.com/developer/msbuild/2003"
>
<Target
Name
=
"Target1"
>
<MSBuild
Targets
=
"Target2"
Projects
=
"$(MSBuildProjectFile)"
Properties
=
"Test=0"
/>
<MSBuild
Targets
=
"Target2"
Projects
=
"$(MSBuildProjectFile)"
Properties
=
"Test=1"
/>
</Target>
<Target
Name
=
"Target2"
>
<Message
Text
=
"Dans Target2: Test=$(Test)"
/>
</Target>
</Project>
Microsoft (R) Build Engine Version 3.5.30729.1
[Microsoft .NET Framework, Version 2.0.50727.3053]
Copyright (C) Microsoft Corporation 2007. All rights reserved.
Build started 27/01/2009 18:16:30.
Project "D:\Input Params avec MsBuild.proj" on node 0 (default targets).
Project "D:\Input Params avec MsBuild.proj" (1) is building "D:\Input Params avec MsBuild.proj" (1:2) on node 0 (Target2 target(s)).
Dans Target2: Test=0
Done Building Project "D:\Input Params avec MsBuild.proj" (Target2 target(s)).
Project "D:\Input Params avec MsBuild.proj" (1) is building "D:\Input Params avec MsBuild.proj" (1:3) on node 0 (Target2 target(s)).
Dans Target2: Test=1
Done Building Project "D:\Input Params avec MsBuild.proj" (Target2 target(s)).
Done Building Project "D:\Input Params avec MsBuild.proj" (default targets).
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:00.09
4-6-3-2. Paramètres de sortie▲
Il est également possible de recevoir des paramètres de sortie lors de l'exécution d'un target. Il peut s'agir soit de propriétés, soit d'items.
<Project
xmlns
=
"http://schemas.microsoft.com/developer/msbuild/2003"
>
<Target
Name
=
"Target1"
>
<!-- Récupération de la sortie lors de l'utilisation de CallTarget -->
<CallTarget
Targets
=
"Target2"
>
<Output
TaskParameter
=
"TargetOutputs"
PropertyName
=
"OutputCallTarget"
/>
</CallTarget>
<Message
Text
=
"Target2 a renvoyé $(OutputCallTarget)"
/>
<!-- Récupération de la sortie lors de l'utilisation de MsBuild -->
<MSBuild
Targets
=
"Target2"
Projects
=
"$(MSBuildProjectFile)"
>
<Output
TaskParameter
=
"TargetOutputs"
PropertyName
=
"OutputMsBuild"
/>
</MSBuild>
<Message
Text
=
"Target2 a renvoyé $(OutputMsBuild)"
/>
</Target>
<Target
Name
=
"Target2"
Outputs
=
"$(OutputProperty)"
>
<CreateProperty
Value
=
"MaValeur"
>
<Output
TaskParameter
=
"Value"
PropertyName
=
"OutputProperty"
/>
</CreateProperty>
</Target>
</Project>
Microsoft (R) Build Engine Version 3.5.30729.1
[Microsoft .NET Framework, Version 2.0.50727.3053]
Copyright (C) Microsoft Corporation 2007. All rights reserved.
Build started 27/01/2009 18:28:36.
Project "D:\Output Params.proj" on node 0 (default targets).
Target2 a renvoyé MaValeur
Target2 a renvoyé MaValeur
Done Building Project "D:\Output Params.proj" (default targets).
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:00.03
Dans l'exemple ci-dessus, nous allons simplement appeler (via les tâches CallTarget et MsBuild) le Target2 présent dans le même fichier.
Ce target se contente de créer une propriété, et spécifie qu'elle va la retourner. On peut alors lire la propriété TargetOutputs des tâches pour récupérer la propriété.
De la même façon, on pourrait récupérer un item. Le fichier ci-dessous nous donnerait exactement le même résultat d'exécution.
On fera bien attention d'utiliser l'attribut ItemName et non plus PropertyName pour la récupération de la valeur.
<Project
xmlns
=
"http://schemas.microsoft.com/developer/msbuild/2003"
>
<Target
Name
=
"Target1"
>
<!-- Récupération de la sortie lors de l'utilisation de CallTarget -->
<CallTarget
Targets
=
"Target2"
>
<Output
TaskParameter
=
"TargetOutputs"
ItemName
=
"OutputCallTarget"
/>
</CallTarget>
<Message
Text
=
"Target2 a renvoyé @(OutputCallTarget)"
/>
<!-- Récupération de la sortie lors de l'utilisation de MsBuild -->
<MSBuild
Targets
=
"Target2"
Projects
=
"$(MSBuildProjectFile)"
>
<Output
TaskParameter
=
"TargetOutputs"
ItemName
=
"OutputMsBuild"
/>
</MSBuild>
<Message
Text
=
"Target2 a renvoyé @(OutputMsBuild)"
/>
</Target>
<Target
Name
=
"Target2"
Outputs
=
"@(OutputItem)"
>
<CreateItem
Include
=
"MaValeur"
>
<Output
TaskParameter
=
"Include"
ItemName
=
"OutputItem"
/>
</CreateItem>
</Target>
</Project>