| Visual Studio 2005: L'essentiel sur MSBuild par Bruno Boucard(boucard.bruno@free.fr) | ||
Remarque : cet article étant fondé sur la version bêta 1 du produit Visual Studio 2005, certaines caractéristiques décrites peuvent être amenées à changer vis-à-vis de la version finale, prévue courant 2005.
Qu'est-ce que MSBuild ? C'est l'outil de construction d'applications .NET à la fois sous Visual Studio 2005 et au sein du Framework .NET 2.0. Pour les développeurs du prochain système d'exploitation "Longhorn", MSBuild est déjà l'outil pour construire de nouvelles applications. Il n'y a aucun doute, MSBuild sera un des éléments incontournables dans les prochains environnements de développement Microsoft. Selon Alex Kipman, Program Manager MSBuild, son produit serait déjà utilisé en interne pour construire les derniers développements Microsoft.
Dans un premier survol, MSBuild ressemble étrangement à NANT, mais après avoir installé Visual Studio 2005, on remarque que l'une des principales qualités du produit MSBuild, est d'être totalement intégré à Visual Studio 2005 sans pour autant en être dépendant. En interne, Visual Studio 2005 est fondé sur MSBuild pour générer les projets. Ainsi les options proposées dans les fenêtres de l'IDE pour personnaliser la construction d'un projet correspondent à des balises spécifiques d'un fichier MSBuild, qui n'est autre qu'un fichier projet. Ces nouveaux fichiers projets sont spécifiques à Visual Studio 2005 et respectifs aux langages de développement utilisés (par exemple l'extension .vbproj pour un projet VB.NET et .csproj pour un projet C#). En d'autres mots, tous les fichiers projets générés par l'IDE sont directement consommables par l'outil MSBuild.exe, et ceci sans la présence de Visual Studio 2005.
Par exemple, supposons un projet C# engendré par Visual Studio 2005 nommé DemoMsBuild ; recopiez ce projet sur une machine disposant seulement du Framework .NET 2.0; puis à la l'aide de la commande ci-dessous, reconstruisez-le tout comme le ferait Visual Studio 2005 via son menu "Build->Rebuild BonjourMsBuild" sur la machine d'origine:
|
01. MSBuild DemoMsBuild.csproj /t:Rebuild |
| Rebuild |
Le commutateur "/t" permet de sélectionner la cible (target) désirée, mais nous reviendrons ultérieurement sur cette notion. Cependant, au lieu de traiter un fichier engendré par Visual Studio 2005, vous pourriez aussi écrire vos propres fichiers projets à la main en respectant le schéma XML MSBuild (le fichier msbuild.xsd est installé avec le Framework .NET 2.0). Dans cet article, vous prendrez connaissance des éléments essentiels de la syntaxe MSBuild, principalement à travers l'outil en ligne de commande.
Avant de plonger dans la syntaxe de fichiers MSBuild, une petite présentation de l'environnement d'exécution sous-jacent à l'utilisation de l'outil devrait vous permettre de mieux appréhender le fonctionnement de cet outil. Conceptuellement un processus MSBuild peut se décrire comme une orchestration de tâches unitaires (création de répertoires, compilation, copie de fichiers...), s'exécutant via un moteur d'exécution dans un environnement géré (managed). Le moteur d'exécution est nourri par un ou plusieurs fichiers projets décris en XML (notons qu'initialement le nom de code du projet MSBuild était XMake, pour XML Make). Sur le plan de l'architecture, le moteur MSBuild est exposé via l'outil en ligne de commande MSBuild.exe, dont le rôle principal est de permettre l'accès au moteur via un jeu de commutateurs à passer sur la ligne de commande.
|
Figure 1. Le moteur MSBuild |
|
01. MSBuild [options] [fichier projet | fichier solution] |
| L'usage de l'outil |
Par défaut, si aucun argument n'est passé en ligne de commande, MSBuild.exe, inspecte le répertoire courant à la recherche d'un fichier dont l'extension se termine par ".proj". Si un tel fichier est trouvé, MSBuild le charge et le traite. Si le répertoire contient plusieurs fichiers ".proj", MSBuild ne lance rien et vous réclame de préciser le fichier projet à traiter. Si un fichier solution Visual Studio 2005 est fourni, l'outil traduit la syntaxe non-MSBuild du fichier solution en une syntaxe MSBuild (la syntaxe des fichiers solutions reste propriétaire à Visual Studio). Enfin vous avez toujours la possibilité d'interrompre proprement un traitement, en frappant la combinaison de touches [Ctrl+C].
| Option longue | Raccourci | Description |
|---|---|---|
| /help | /h ou / ? | Montre le message d'usage. |
| /nologo | Supprime la bannière et le message de copyright. | |
| /version | /ver | Montre les informations au sujet de la version. |
| @<fichier> | Permet de placer dans un fichier des options complémentaires à la ligne de commande. | |
| /quiet | /q | |
| /verbosity:<level> | /v | Redirige vers le logger d'évènement les messages émis par les tâches en fonction du niveau <level> de verbosité réclamé. Du moins verbeux, au plus verbeux: q[uiet], m[inimal], n[ormal], d[etailed], diag[nostic]. |
| /target :<liste de cibles> | /t | Spécifie la liste de cibles à construire (séparées par un point virgule) contenu dan le fichier projet. |
| /property :<nom>=<valeur> | /p | Spécifie la liste de propriétés (séparées par un point virgule) contenu dan le fichier projet. Une propriété est un couple composé du nom et de sa valeur. |
| /logger :<logger> | /l | Enregistre un logger à l'écoute des évènements MSBuild. |
| /noconsolelogger | /noconlog | Désactive le logger de console. |
| /validate[:<schema>] | /val | Valide le fichier projet contre le schéma XML défaut ou celui fournit en paramètre. |
Pour illustrer l'introduction à MSBuild, j'ai choisi de construire progressivement un exemple composé d'une application minimaliste et de deux librairies.
L'exemple se décline en une application console, "app.exe" écrite en C#, reposant sur la librairie d'interface "imath.dll" écrite elle aussi en C#. La libraire d'implémentation "math.dll" est composée de deux modules: "simple.netmodule" écrit en C# et "advanced.netmodule" écrit en Java et repose sur la librairie d'interface précédente. Les deux assemblages "IMath" et "Math" sont signés et le dernier s'installe dans le GAC.
Le schéma ci-dessous rappelle comment engendrer via les compilateurs en ligne, les binaires de l'application à partir des divers fichiers sources.
|
Figure 2. Chaîne de construction |
Je reconnais que la complexité engendrée par tous ces fichiers est discutable, mais ce n'est qu'un prétexte pour illustrer MSBuild.
Pour compléter les informations concernant l'exemple, voici les codes sources répartis par assemblage : IMath, Math et App.
L'assemblage IMath ne contient que des interfaces définis dans un seul fichier : imath.cs.
|
01. // imath.cs 02. using System.Reflection; 03. using System.Runtime.CompilerServices; 04. using System; 05. 06. [assembly: AssemblyVersion("1.0.0.0")] 07. 08. namespace Dotnet.Math 09. { 10. public interface ISum 11. { 12. double Sum(double a, double b); 13. } 14. 15. public interface ISubstract 16. { 17. double Substract(double a, double b); 18. } 19. 20. public interface IMultiply 21. { 22. double Multiply(double a, double b); 23. } 24. 25. public interface IDivide 26. { 27. double Divide(double a, double b); 28. } 29. } |
| IMath.cs |
L'assemblage Math est composé de deux modules .NET et d'une DLL:
Simple.netmodule : simple.cs
Advanced.netmodule : advanced.java
Math.dll : math.cs
|
01. using System; 02. 03. namespace Dotnet.Math 04. { 05. internal class Simple : ISum, ISubstract 06. { 07. 08. public double Sum(double a, double b) 09. { 10. return a + b; 11. } 12. 13. public double Substract(double a, double b) 14. { 15. return a - b; 16. } 17. 18. public static void Main() 19. { 20. double a = 1; 21. double b = 2; 22. 23. Simple instance = new Simple(); 24. 25. Console.WriteLine("Sum({0}, {1}) = {2}", a, b, instance.Sum(a, b)); 26. Console.WriteLine("Substract({0}, {1}) = {2}", a, b, instance.Substract(a, b)); 27. } 28. }; 29. } |
| Simple.cs |
La classe Simple contient une méthode Main(), offrant l'opportunité de tester le module.
|
01. package Dotnet.Math; 02. 03. public class Advanced implements IMultiply, IDivide 04. { 05. public double Multiply(double a, double b) 06. { 07. return a * b; 08. } 09. 10. public double Divide(double a, double b) 11. { 12. return a / b; 13. } 14. } |
| Advanced.java |
Le fichier math.cs ne contient rien, mis à part l'attribut d'assemblage AssemblyVersion.
|
01. using System.Reflection; 02. using System.Runtime.CompilerServices; 03. 04. [assembly: AssemblyVersion("1.0.0.0")] |
| Math.java |
L'assemblage App consomme simplement les services de la librairie d'interface IMath.DLL, découplant physiquement ainsi l'application de l'implémentation de librairie Math.DLL.
|
01. using System; 02. using System.Reflection; 03. using Dotnet.Math; 04. 05. class App 06. { 07. static void Main() 08. { 09. double a = 1; 10. double b = 2; 11. 12. Assembly asm = Assembly.Load("Math"); 13. 14. IMultiply mul = (IMultiply)asm.CreateInstance("Dotnet.Math.Advanced"); 15. IDivide div = (IDivide)mul; 16. 17. Console.WriteLine("Multiply({0}, {1}) = {2}", a, b, mul.Multiply(a, b)); 18. Console.WriteLine("Divide({0}, {1}) = {2}", a, b, div.Divide(a, b)); 19. 20. ISum sum = (ISum)asm.CreateInstance("Dotnet.Math.Simple"); 21. ISubstract sub = (ISubstract)sum; 22. 23. Console.WriteLine("Sum({0}, {1}) = {2}", a, b, sum.Sum(a, b)); 24. Console.WriteLine("Substract({0}, {1}) = {2}", a, b, sub.Substract(a, b)); 25. } 26. } |
| App.cs |
Avant de se lancer dans la confection de projets opérationnels, nous allons introduire point par point la syntaxe de base MSBuild.
Sous MSBuild tout commence par un projet. Tous les fichiers MSBuild se doivent de définir un élément XML racine appelé <Projet>. Par exemple, supposons un fichier "demo1.proj" contenant le texte suivant :
|
01. <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"/> |
| demo1.proj |
Noter que l'espace de noms "http://schemas.microsoft.com/developer/msbuild/2003" est obligatoire. Pour valider ce premier projet (minimaliste) lançons la commande MSBuild et observons le résultat :
|
Figure 3. Demo1.proj |
Aucune cible (target) n'a été précisée sur la ligne de commande et pour cause notre fichier "demo1.proj" est vide. En effet, n'ayant pas défini de cible, le moteur MSBuild en recherche une en vain et nous retourne l'erreur MSB4040. Ceci nous amène à rappeler la première vocation de MSBuild : lancer un ou plusieurs traitements (tâches) réunis sous une ou plusieurs cibles.
Par définition une cible (target) réuni un ensemble de tâches. Vous pouvez nommer une cible via l'attribut "Name" de manière à la désigner explicitement, comme sur la ligne de commande via le commutateur "/t". Par exemple dans le fichier "demo2.proj" nous avons défini une cible (vide de tâches) nommée "ConstruireMath".
|
01. <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 02. <Target Name="ConstruireMath"/> 03. </Project> |
| demo2.proj |
Testons ce projet :
|
Figure 4. Demo2.proj |
Le moteur MSBuild a détecté notre cible "ConstruireMath".
Ajoutons que l'élément racine <Projet> permet de définir l'attribut DefaultTargets, désignant une liste défaut composée de cibles séparées par des points virgules (;) . L'exemple ci-dessous définit trois cibles à exécuter dans l'ordre suivant :
ConstruireIMath
ConstruireMath
ConstruireApp
|
01. <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="ConstruireIMath; ConstruireMath; ConstruireApp"> 02. <Target Name="ConstruireMath"/> 03. <Target Name="ConstruireIMath"/> 04. <Target Name="ConstruireApp"/> 05. </Project> |
| demo2.proj |
L'exemple précédent ne nous permet pas d'ordonnancer les cibles entre elles. Pour répondre à ce besoin, l'attribut DependsOnTargets de l'élément <Target> permet de lister des cibles dépendantes à traiter avant celle-ci.
|
01. <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="ConstruireApp"> 02. <Target Name="ConstruireMath"/> 03. <Target Name="ConstruireIMath"/> 04. <Target Name="ConstruireApp" DependsOnTargets=" ConstruireIMath; ConstruireMath"/> 05. </Project> |
| demo2.proj |
Je dois reconnaître que l'intérêt de ces fichiers reste fort limité, car pour l'instant nous n'avons toujours pas lancé un seul traitement.
La vocation première de MSBuild est de lancer des traitements adaptés au processus de développement, comme la compilation, l'édition de liens, mais aussi les tests unitaires, le déploiement ... Les traitements sont concrétisés à travers la notion de tâche. Au sein d'une cible, vous avez la possibilité de définir des tâches dédiées à votre processus de construction.
Par défaut MSBuild propose l'ensemble de tâches prédéfinies :
| Tâche | Description |
|---|---|
| AL | Edition de lien pour assemblage, fondée sur l'outil AL.exe. Particulièrement utile pour les assemblages multi-modules. |
| Copy | Copier des fichiers vers une nouvelle destination. |
| CreateItem | Peuple une liste d'items passés en paramètre. Ceci permet de copier des items d'une liste à l'autre. |
| CreateProperty | Peuple des propriétés avec des valeurs passées en entrée |
| Csc | Fondée sur le compilateur C#, CSC.exe, cette tâche produit des binaires identiques à ceux de l'outil : .exe, .dll, .netmodule. |
| Delete | Efface des fichiers. |
| Exec | Exécute une commande système comme si elle était lancée depuis une fenêtre "command prompt". |
| GenerateApplication Manifest | Génère un assemblage de type manifeste pour une application Win32 ou ClickOnce. |
| GenerateDeploymentManifest | Génère un manifeste de déploiement ClickOnce. |
| LC | Fondé sur le compilateur de licence qui génère un fichier .licence depuis un fichier .licx. |
| MakeDir | Création de répertoires |
| MSBuild | Construit des projets fondés sur MSBuild.exe lui-même. |
| RegisterAssembly | Similaire à l'outil framework, RegAsm.exe, cette tâche examine les métas données d'un assemblage pour générer les entrées nécessaires dans le Registre de manière à lancer les classes de cet assemblage comme des composants COM vis-à-vis de clients COM. |
| RemoveDir | Efface des répertoires et leurs fichiers respectifs. |
| RegGen | Similaire à l'outil du framework, ResGen.exe, cette tâche converti un fichier .txt ou .resx en fichier de ressources binaire .NET. |
| ResolveAssemblyReference | Cette tâche prend en entrée un ou plusieurs noms d'assemblages et localise ces noms répartis dans des répertoires sur le disque ou dans le cache global des assemblages (GAC), voir dans la ruche du registre. |
| ResolveCOMReference | Cette tâche prend en entrée un ou plusieurs noms de librairie COM ou fichiers .tlb et localise ceux-ci sur le disque. |
| Touch | Positionne les droits d'accès des fichiers et modifie leurs dates. |
| UnregisterAssembly | Réalise la tâche inverse de RegisterAssembly. |
| Vbc | Equivalent au compilateur VB.NET, vbc.exe, cette tâche produit des binaires identiques à ceux de l'outil : .exe, dll, .netmodule. |
| VCBuild | Exécute le constructeur d'applications fondées sur des projets Visual C++. |
Pour illustrer l'utilisation d'une tâche, voici l'exemple "Demo3.proj" fondé sur l'usage de la tâche "MakeDir". Ici nous utilisons l'attribut Directories pour renseigner la liste des répertoires à créer.
|
01. <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 02. <Target Name="CreationDeRepertoire"> 03. <MakeDir Directories= "bin"/> 04. </Target> 05. </Project> |
| demo3.proj |
Lançons ce projet :
|
Figure 5. Demo3.proj |
Le moteur MSBuild a détecté la cible "CreationDeRepertoire" et nous informe que la tâche MakeDir a créé le répertoire "bin". Notez que si le répertoire existe déjà, la tâche ne fait pas d'erreur.
Une fois encore l'intérêt de cette démonstration est discutable, car nous aurions aimé définir des variables au lieu de coder en dur la chaîne "bin". La majorité des tâches exposent des interfaces d'entrées/sorties bien plus complexes que l'exemple "demo3.proj" et dans ce cadre l'usage de définitions organisées en items et en propriétés dévient une nécessité.
La notion d'item, permet de définir des valeurs disponibles au niveau du projet et donc accessibles par ses tâches sous-jacentes. Généralement, les items représentent les fichiers à compiler. La syntaxe MSBuild permettant de définir une liste d'items est basée sur l'élément XML <ItemGroup>. Par exemple, nous pourrions définir les items définissant le fichier à compiler et le type d'exécutable à engendrer:
|
01. <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="ConstruireIMath"> 02. <ItemGroup> 03. <FichierACompiler Include="imath.cs"/> 04. <ExecutableType Include= "library"/> 05. </ItemGroup> 06. <Target Name="ConstruireIMath"> 07. <Csc 08. Sources="@(FichierACompiler)" 09. TargetType="@(ExecutableType)" 10. EmitDebugInformation="true" 11. KeyFile="public.snk" 12. DelaySign="true"/> 13. </Target> 14. </Project> |
| demo4.proj |
Ici, nous souhaitons obtenir un assemblage de type DLL signé "retardé" en mode Debug. Dans ce projet j'ai défini, un élément <ItemGroup> dont la vocation est de grouper des items ; ici FichierACompiler et ExecutableType. On note que l'accès à la valeur d'un item prend la syntaxe @(nom de item ). Si nous avions plusieurs items à traiter, nous pourrions utiliser différentes syntaxes :
Un wildcard comme "*.cs" combiné éventuellement avec l'attribut Exclude pour retirer certains items :
<FichierACompiler Include=”*.cs” Exclude= "imath.cs"/>.
Vous pourriez aussi spécifier chaque item en répétant par exemple l'élément FichierACompiler pour chaque fichier ".cs".
Enfin vous pourriez lister au sein d'un item, un ensemble de valeurs séparées par des points virgules.
Les deux exemples suivants résument les principales pratiques de l'élément <ItemGroup> :
|
01. <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 02. <ItemGroup> 03. <FichierJavaACompiler Include="advanced.java"/> 04. <ListeDeFichiersCSharpACompiler Include="math.cs ; simple.cs"/> 05. </ItemGroup> 06. </Project> |
| demo4.proj |
Avec l'usage de WildCards, le code est plus concis :
|
01. <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 02. <ItemGroup Exclude= " imath2.cs "> 03. <FichierJavaACompiler Include="*.java"/> 04. <FichiersCCompiler Include="*.cs"/> 05. </ItemGroup> 06. </Project> |
| demo4.proj |
Dans le paragraphe précèdent, nous avons appris que les items étaient essentiels pour nourrir les tâches MSBuild. Cependant il existe un moyen complémentaire pour paramétrer les tâches : les propriétés.
Les propriétés offrent la capacité de caractériser les tâches. Elles proposent le formaliste clef/valeur, dont la syntaxe est fondée sur l'élément XML <PropertyGroup>. Par exemple, nous pourrions définir un groupe composé de trois propriétés, InformationDebug, FichierClef et SignatureRetarde. Dans le projet suivant nous définissons la cible "ConstruireIMath», contenant une tâche C#, dont les paramètres sont répartis à la fois dans des items et des propriétés :
|
01. <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="ConstruireIMath"> 02. <PropertyGroup> 03. <InformationDebug>true</InformationDebug> 04. <FichierClef>publicprive.snk</FichierClef> 05. <SignatureRetarde>false</SignatureRetarde> 06. </PropertyGroup> 07. <ItemGroup> 08. <FichierACompiler Include="imath.cs"/> 09. <ExecutableType Include= "library"/> 10. </ItemGroup> 11. <Target Name="ConstruireIMath"> 12. <Csc 13. Sources="@(FichierACompiler)" 14. TargetType="@(ExecutableType)" 15. EmitDebugInformation="$(InformationDebug)" 16. KeyFile="$(FichierClef)" 17. DelaySign="$(SignatureRetarde)" 18. /> 19. </Target> 20. </Project> |
| demo5.proj |
On note que l'accès aux valeurs d'une propriété au sein d'une tâche prend la syntaxe $(nom de propriété).
|
Figure 6. Demo5.proj |
Dans le cadre des propriétés, sachez que MSBuild définit les siennes.
| Nom de la propriété | Description | Exemple |
|---|---|---|
| MSBuildProjectDirectory | Répertoire dan lequel le projet est stocké | C:\MSBUILD |
| MSBuildProjetFile | Nom du fichier projet | BonjourMSBuild.proj |
| MSBuildProjectExtension | Extension du fichier projet | .proj |
| MSBuildProjectFullPath | Chemin complet du fichier projet | C:\MSBuild\BonjourMSBuild.proj |
| MSBuildProjectName | Nom du fichier projet sans l'extension | BonjourMSBuild |
| MSBuildPath | Répertoire dans lequel msbuild.exe est stocké | C:\WINDOWS\Microsoft.NET\Framework\v2.0. 40607\MSBuild.exe |
Notez que vous ne pouvez pas utiliser ces noms dans vos définitions de propriétés car ils sont naturellement réservés.
Précédemment, nous avons appris que les propriétés et les items étaient conçus pour découpler les paramètres des tâches elles-mêmes. Typiquement, nous pourrions découper les items, les propriétés et les cibles pour un gain de visibilité et de maintenance. La syntaxe MSBuild permet d'importer dans un projet, un autre projet, via l'élément <Import>.
La démonstration précédente peut se découper en trois sous-projets :
|
01. <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="ConstruireIMath"> 02. <ItemGroup> 03. <FichierACompiler Include="imath.cs"/> 04. <ExecutableType Include= "library"/> 05. </ItemGroup> 06. <Import Project="demo5.properties.proj"/> 07. <Import Project="demo5.targets.proj"/> 08. </Project> |
| demo5.main.proj |
|
01. <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 02. <PropertyGroup> 03. <InformationDebug>true</InformationDebug> 04. <FichierClef>publicprive.snk</FichierClef> 05. <SignatureRetarde>false</SignatureRetarde> 06. </PropertyGroup> 07. </Project> |
| demo5.properties.proj |
|
01. <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 02. <Target Name="ConstruireIMath"> 03. <Csc 04. Sources="@(FichierACompiler)" 05. TargetType="@(ExecutableType)" 06. EmitDebugInformation="$(InformationDebug)" 07. KeyFile="$(FichierClef)" 08. DelaySign="$(SignatureRetarde)" 09. /> 10. </Target> 11. </Project> |
| demo5.targets.proj |
Du point de vue technique, l'élément <Import> s'apparente à l'ordre #include du pré-processeur des compilateurs C/C++. Le code contenu dans le fichier importé est injecté là où l'élément <Import> a été placé.
Nous savons maintenant organiser de manière modulaire notre processus de construction. Cependant, il est parfois légitime de vouloir prendre le résultat d'une tâche pour le placer en entrée d'une autre. Par nature les tâches ne peuvent communiquer entre elles directement, elles doivent impérativement utiliser des variables intermédiaires. Pour ce faire, MSBuild définit "un item de sortie", permettant d'associer un paramètre d'une tâche avec un nom d'item dont la syntaxe est la suivante :
| Output |
Pour illustrer l'usage d'un "item de sortie", je propose les fichiers demo6.main.proj, demo6.properties.proj, demo6.targets.proj:
|
01. <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="ConstruireTestSimple"> 02. <ItemGroup> 03. <FichierACompiler Include="simple.cs"/> 04. <References Include="imath.dll"/> 05. <ExecutableType Include="module"/> 06. </ItemGroup> 07. <Import Project="demo6.properties.proj"/> 08. <Import Project="demo6.targets.proj"/> 09. </Project> |
| demo6.main.proj |
|
01. <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 02. <PropertyGroup> 03. <InformationDebug>true</InformationDebug> 04. <PointEntreePrincipal>Dotnet.Math.Simple.Main</PointEntreePrincipal> 05. <FichierClef>publicprive.snk</FichierClef> 06. <SignatureRetarde>false</SignatureRetarde> 07. </PropertyGroup> 08. </Project> |
| demo6.properties.proj |
|
01. <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 02. <Target Name="ConstruireSimple"> 03. <Csc 04. EmitDebugInformation="$(InformationDebug)" 05. References="@(References)" 06. TargetType="@(ExecutableType)" 07. Sources="@(FichierACompiler)"> 08. <Output 09. ItemName="NomDuModule" 10. TaskParameter="OutputAssembly" 11. /> 12. </Csc> 13. </Target> 14. <Target Name="ConstruireTestSimple" DefaultTargets="ConstruireSimple"> 15. <AL 16. MainEntryPoint="$(PointEntreePrincipal)" 17. SourceModules="@(NomDuModule)" 18. TargetType="exe" 19. KeyFile="$(FichierClef)" 20. DelaySign="$(SignatureRetarde)" 21. OutputAssembly="@(NomDuModule->'%(FileName)').exe" 22. Version="1.0.0.0" 23. /> 24. </Target> 25. </Project> |
| demo6.targets.proj |
L'item NomDuModule permet d'édifier un lien entre deux tâches, ici <Csc> et <AL>.
Dans le fichier "demo6.targets.proj" j'ai utilisé une instruction de transformation dans le cadre de la tâche AL de manière à extraire le nom du fichier sans l'extension de l'item NomDuModule (simple.netmodule) :
OutputAssembly="@(NomDuModule->'%(FileName)').exe"
La motivation des transformations est d'extraire des éléments d'une chaîne contenant un nom de fichier. Voici une liste non exhaustive des transformations courantes.
| Transformation | C:\MSBuild\bin\source.exe |
|---|---|
| %{FileName} | Source |
| %{Extension} | .exe |
| %{RelativeDir} | C:\MSBuild\bin\ |
| %{FullPath} | C:\MSBuild\bin\source.exe |
Généralement, dans les environnements de développements nous souhaitons générer au moins deux types de distribution : Debug et Release (nous avons pour l'instant généré des modules exclusivement en mode Debug). Pour répondre à ce type de besoin, MSBuild propose un attribut Condition permettant de conditionner la plupart des éléments sur les opérateurs suivants :
| Condition | Description |
|---|---|
| ‘Chaîne1' == ‘Chaîne2' | Retourne vraie si Chaîne1 est égale à Chaîne2. |
| ‘Chaîne1' != ‘Chaîne2' | Retourne vraie si Chaîne1 n'est pas égale à Chaîne2. |
| Exists(‘Chaîne1') | Retourne vraie si le fichier ou le répertoire nommé Chaîne1 existe. |
| !Exists(‘Chaîne1') | Retourne vraie si le fichier ou le répertoire nommé Chaîne1 n'existe pas |
Il existe un élément nommé <Error> permettant de rattraper des erreurs sur condition. Par exemple nous aimerions indiquer à l'utilisateur un message d'erreur lorsque celui n'indique pas une propriété testée dans une conditi