IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Intégration Continue avec Visual Studio et Team Foundation Server - Partie II, Présentation de MsBuild et de TfsBuild

Intégration Continue avec Visual Studio et Team Foundation Server - Partie II, Présentation de MsBuild et de TfsBuild


précédentsommairesuivant

5. Factoriser un fichier de build

5-1. Principes de factorisation

Un fichier de build doit être considéré comme un élément de code à part entière et doit donc suivre la même logique et réflexion lors de sa création. Ce fichier sera donc également factorisé et refactoré. Ne perdez pas de vue en effet qu'un fichier de build sur un projet important peut rapidement atteindre plusieurs centaines - voire milliers - de lignes.

Parmi les différents critères auxquels il faudra veiller, on peut citer entre autres :

  • Commentaires du code
  • Principe de responsabilité unique dans un même target
  • Pas de redondance du code
  • Extraction des fonctionnalités communes dans une bibliothèque partagée

Il est évidemment très simple de commenter son fichier de build.

Et nous avons déjà vu comment il est possible de créer des target, de les appeler, de créer des dépendances entre eux, ou encore comment envoyer des paramètres et recevoir des valeurs en retour. Par conséquent il est également très simple de répondre à la notion de responsabilité.

La redondance de code quant elle peut également être évitée via la factorisation dans d'autres targets.

Si on se place maintenant dans une problématique plus large avec la création de fichiers de build pour plusieurs projets, la notion de bibliothèque de target peut devenir très intéressante de façon à regrouper certaines tâches communément réalisées.

Microsoft utilise à cette fin l'extension « .targets », comme c'est le cas pour le fichier « Microsoft.CSharp.targets » par exemple.

5-2. Utilisation de fichier .targets

Il est possible de faire référence à un autre fichier de projet afin de mutualiser du code. Pour cela, on utilise l'élément « Import ».

Import du fichier « Commun.targets »
Sélectionnez
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <Import Project="Commun.targets"/>
</Project>

Notez que cet élément peut être déclaré à n'importe quel endroit du fichier de projet.

Il faut visualiser le fonctionnement de cette commande comme une copie du contenu du fichier importé à l'emplacement où la commande est déclarée.

5-3. Précautions à observer

Si l'utilisation de fichier d'import est très pratique pour factoriser et partager le code - elle est d'ailleurs massivement utilisée par Microsoft pour mutualiser les fichiers de projet - certaines précautions sont à observer.

5-3-1. Positionnement de la commande d'Import

L'emplacement auquel on déclare la commande d'import peut avoir des conséquences sur le fonctionnement du fichier de build.

Pour s'en rendre compte, il faut se souvenir qu'un fichier de build est toujours traité de bas en haut. Ainsi on peut prendre deux exemples : le premier nous montrera la redéfinition d'une propriété, et le suivant nous permettra de faire une redéfinition d'un target.

Pour ces exemples, nous allons nous baser sur le fichier commun suivant :

Déclaration d'un fichier .targets : « Commun.targets »
Sélectionnez
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

   <PropertyGroup>
      <MaPropriete>Valeur Par Défaut</MaPropriete>
   </PropertyGroup>

   <Target Name="Go">
      <Message Text="Dans le fichier commun : $(MaPropriete)"/>
   </Target>

</Project>

5-3-1-1. Redéfinition d'une propriété

Comme les propriétés sont initialisées de haut en bas, selon l'emplacement de la ligne d'Import, on peut permettre de redéfinir la valeur d'une propriété.

Ainsi dans le cas suivant :

Utilisation du fichier « Commun.targets » - Exemple 1
Sélectionnez
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  
   <PropertyGroup>
      <MaPropriete>Nouvelle valeur</MaPropriete>
   </PropertyGroup>

   <Import Project="Commun.targets" />

</Project>

Si on visualise la copie du contenu du fichier « Commun.targets », on aurait l'assignation de « Nouvelle Valeur » dans la propriété, puis l'assignation de « Valeur Par Défaut ». En toute logique, nous obtenons le résultat d'exécution suivant :

Résultat de l'utilisation du fichier « Commun.targets » - Exemple 1
Sélectionnez
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 12/05/2009 21:46:46.
Project "C:\Temp\build.proj" on node 0 (default targets).
  Dans le fichier commun : Valeur Par Défaut
Done Building Project "C:\Temp\build.proj" (default targets).

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:00.23

Si en revanche, nous positionnons la commande d'Import en début de fichier, alors le résultat change totalement :

Utilisation du fichier « Commun.targets » - Exemple 2
Sélectionnez
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  
   <Import Project="Commun.targets" />

   <PropertyGroup>
      <MaPropriete>Nouvelle valeur</MaPropriete>
   </PropertyGroup>

</Project>
 
Sélectionnez
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 12/05/2009 21:48:24.
Project "C:\Temp\build.proj" on node 0 (default targets).
  Dans le fichier commun : Nouvelle valeur
Done Building Project "C:\Temp\build.proj" (default targets).

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:00.03

Si on déclare deux propriétés statiques avec le même nom, c'est alors la deuxième valeur qui sera assignée à la propriété (ie. celle qui est présente le plus bas dans le fichier).
Si on déclare deux propriétés dynamiques (ou une statique et une dynamique) avec le même nom, c'est la valeur de la dernière qui est créée (donc exécutée) qui sera assignée à la propriété.
C'est sur ce principe que l'on peut changer la valeur d'une propriété. Se référer à la section « Changer la valeur d'une propriété » pour plus d'informations.

5-3-1-2. Redéfinition d'un target

Si l'on re-déclare un target nommé « Go » dans le fichier .proj, alors on pourra redéfinir le target original selon l'emplacement de la commande d'Import.

Supposons par exemple le cas suivant :

Utilisation du fichier « Commun.targets » - Exemple 3
Sélectionnez
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

   <Target Name="Go">
      <Message Text="Dans le fichier .proj : $(MaPropriete)"/>
   </Target>

   <Import Project="Commun.targets" />

</Project>
 
Sélectionnez
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 12/05/2009 21:50:13.
Project "C:\Temp\build.proj" on node 0 (default targets).
  Dans le fichier commun : Valeur Par Défaut
Done Building Project "C:\Temp\build.proj" (default targets).

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:00.01

Ici nous allons rencontrer le target « Go » tout d'abord dans sa définition dans le fichier .proj, puis la version du fichier « .targets ». C'est donc naturellement elle qui sera exécutée.

Par contre, si on définit la commande d'import en en-tête de fichier, alors c'est la version du fichier .proj qui sera conservée.

Utilisation du fichier « Commun.targets » - Exemple 4
Sélectionnez
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

   <Import Project="Commun.targets" />

   <Target Name="Go">
      <Message Text="Dans le fichier .proj : $(MaPropriete)"/>
   </Target>

</Project>
 
Sélectionnez
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 12/05/2009 21:55:17.
Project "C:\Temp\build.proj" on node 0 (default targets).
  Dans le fichier .proj : Valeur Par Défaut
Done Building Project "C:\Temp\build.proj" (default targets).

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:00.01

Si on déclare deux targets avec le même nom, alors seul le dernier existe réellement. C'est ainsi que l'on peut « surcharger » ou redéfinir un target.
Cette solution est massivement utilisée dans les fichiers de Visual Studio, de façon à laisser au développeur des « points d'accroche » dans l'automatisation de certaines tâches (compilation, intégration continue, ...)

5-3-2. Importer un fichier du source control

Il faut savoir que les commandes d'Import sont exécutées en priorité, avant même l'initialisation des propriétés et items statiques.

De plus, le fichier que l'on importe doit impérativement se trouver sur le disque.

Par conséquent il n'est pas possible de référencer un fichier dans le Source Control, et il n'est pas possible de faire un « Get » de fichier dans le Source Control avant que les imports ne soient effectués.

Par conséquent, si vous désirez vraiment utiliser un fichier commun présent dans le Source Control, la seule solution est au sein d'une tâche du fichier de faire un Get pour copier le fichier localement, et puis de déléguer les appels au fichier commun en utilisant la tâche MSBuild.

On perd évidemment dans ce cas la possibilité de redéfinition de propriétés et de targets, et nous devons donc coder nous-même des redirections.


précédentsommairesuivant

Copyright © 2009 Pierre-Emmanuel Dautreppe . Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts. Droits de diffusion permanents accordés à Developpez LLC.