2009-07-06 4 views
10

J'ai une solution que j'essaie de développer sur TFS. Je veux mettre à jour les versions de tous les fichiers appropriés, et j'ai été bloqué en essayant d'y arriver. Il y a beaucoup de liens sur la façon de le faire, mais aucun d'entre eux ne fonctionne pour moi, en raison d'un petit problème ... Scope.Élément ItemGroup, autrement dit "Pourquoi MSBuild me déteste?"

<?xml version="1.0" encoding="utf-8"?> 
<Project DefaultTargets="DesktopBuild" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5"> 
    <Target Name="DesktopBuild"> 
     <CallTarget Targets="GetFiles" /> 

     <Message Text="CSFiles: '@(CSFiles)'" /> 
    </Target> 

    <Target Name="GetFiles"> 
     <ItemGroup> 
      <CSFiles Include="**\AssemblyInfo.cs" /> 
     </ItemGroup> 
     <Message Text="CSFiles: '@(CSFiles)'" /> 
    </Target> 
</Project> 

Mon arbre ressemble à ceci:

  • test.proj
  • application.sln
  • application (dossier)
    • main.cs
    • Propriétés (dossier)
      • AssemblyInfo.cs

Quand je lance "c: \ Windows \ Microsoft.NET \ Framework \ v3.5 \ MSBuild.exe test.proj" à partir du dossier de solution ... je reçois la sortie suivante:

Microsoft (R) Build Engine Version 3.5.30729.1 
[Microsoft .NET Framework, Version 2.0.50727.3074] 
Copyright (C) Microsoft Corporation 2007. All rights reserved. 

Build started 7/6/2009 3:54:10 PM. 
Project "D:\src\test.proj" on node 0 (default targets). 
    CSFiles: 'application\Properties\AssemblyInfo.cs' 
DesktopBuild: 
    CSFiles: '' 
Done Building Project "D:\src\test.proj" (default targets). 


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

Time Elapsed 00:00:00.04 

Alors, comment puis-je faire en sorte que mon ItemGroup ait une portée globale? Tous les fichiers de Targets utilisés par le compilateur et TeamBuild font la même chose, et tous semblent être globaux ... Je ne comprends pas pourquoi cela ne marche pas pour moi.

Une aide?

+0

Essayez-vous de créer le fichier test.proj? Je ne suis pas sûr de comprendre pourquoi vous spécifiez AssemblyInfo.cs plutôt que de construire à partir du fichier de projet. –

+0

J'ai construit le fichier test.proj comme un exemple minimal montrant mon problème. En réalité, j'essaye de construire mon fichier de solution multiple dans TFS. Ceci est juste pour illustrer le comportement de scoping que je vois dans ItemGroups et Targets. –

+0

Je voudrais pouvoir upvoter toutes les personnes qui essaient d'aider, mais apparemment je suis trop 'newb'. Je voulais juste laisser tomber une note que j'apprécie le temps que tout le monde ici a passé à regarder, et à y penser. –

Répondre

9

Avez-vous essayé d'utiliser DependsOnTarget plutôt que CallTarget? Il se peut que CallTarget provoque le problème de portée.

+0

OK, cela semble me donner plus d'informations. Je peux changer la portée du ItemGroup en utilisant DependsOn, mais cela ne semble pas cohérent. Il semble que les frères et sœurs des cibles appelées avec dependson aient accès au groupe d'items, mais le parent ne le fait jamais. Tellement bizarre. Existe-t-il des documents indiquant les règles de portée? Je ne pouvais pas les trouver, et je suppose que maintenant je dois réécrire mes fichiers en utilisant des dépendances complexes plutôt que des appels. C'est tellement fou. –

+0

Je n'en ai vu aucun. Avez-vous essayé de déplacer le ItemGroup en dehors des cibles? Y a-t-il une raison pour laquelle vous ne voulez pas faire cela? – technophile

+0

Ou initialisez-le à l'extérieur pour vider (pirater avec Include = "*. WontExist") –

0

Nous faisons quelque chose de similaire dans notre construction. Nous passons la version en tant que paramètre de ligne de commande.

Dans notre TFSBuild.proj nous mis la version à 0.0.0.0 si aucune version a été fournie:

<!--Our assembly version. Pass it in from the command prompt like this: /property:Version=1.0.0.0--> 
<PropertyGroup> 
    <Version>0.0.0.0</Version> 
</PropertyGroup> 

<PropertyGroup> 
    <!--Used to ensure there is a newline before our text to not break the .cs files if there is no newline at the end of the file.--> 
    <newLine>%0D%0A</newLine> 

Alors nous faisons ceci:

<Target Name="BeforeCompile"> 
    <!--Update our assembly version. Pass it in from the command prompt like this: /property:Version=1.0.0.0--> 

    <!--attrib needs to be run first to remove the read only attribute since files from tfs are read only by default.--> 
    <Exec Command='attrib -R $(SolutionRoot)\Source\Project\GlobalAssemblyInfo.cs' /> 

    <WriteLinesToFile File="$(SolutionRoot)\Source\Project\GlobalAssemblyInfo.cs" 
         Lines='$(newLine)[assembly: AssemblyVersion("$(Version)")]'/> 

</Target> 
+2

Juste pour info, Exists ne fait pas ce que ce code semble l'attendre. Existe pour vérifier si le fichier nommé existe et non si la variable nommée existe. Vous voulez probablement Condition = "'$ (Version)' == ''" à la place. Voir http://msdn.microsoft.com/en-us/library/7szfhaft.aspx – technophile

+0

Ce gars technophile est intelligent. :-) Ce qu'il a dit. La méthode standard doc est d'entourer de guillemets simples et de mettre beaucoup d'espaces autour ... Aussi, cette méthode n'est pas génial pour moi . Je préfère les méthodes de tâches de la communauté MSBuild à attrib et regex mettre à jour les fichiers. Mon problème est de construire la liste de fichiers à mettre à jour, car j'ai des emplacements dynamiques. Merci quand même. :-) –

+0

Merci Chris. :) Nous sommes en train de faire un tas de travail sur notre environnement CI, donc tout cela est très frais dans mon esprit. ;) – technophile

5

L'intervenant précédent était correct, vous devriez changez ceci pour utiliser DependsOnTargets au lieu d'utiliser la tâche CallTarget. Ce que vous voyez est un bug pas une entrée de gamme. Le way to avoid ce bug est d'utiliser DependsOnTargets (ce qui est une bien meilleure approche anywayz).

Sayed Ibrahim Hashimi

Mon livre: Inside the Microsoft Build Engine : Using MSBuild and Team Foundation Build

+0

Est-ce vraiment un bug? L'explication proposée [ici] (http://blogs.msdn.com/b/aaronhallberg/archive/2007/07/16/msbuild-property-evaluation.aspx) est tout aussi convaincante, et est corroborée par le fait que c'est encore comment cela fonctionne, plusieurs années plus tard. –

+0

C'est un bug, s'il vous plaît voir http://blogs.msdn.com/b/msbuild/archive/2006/01/03/508629.aspx –

1

Comme dit, vous devez utiliser DependsOnTargets. J'ai fait quelques recherches sur MSBuild scope, vous pouvez trouver mes résultats sur mon blog: http://blog.qetza.net/2009/10/23/scope-of-properties-and-item-in-an-msbuild-script/

Le truc c'est qu'il semble y avoir une portée globale pour le projet et une portée locale pour la cible. Lors de la saisie de la cible, la portée globale est copiée et lorsque vous quittez la cible, la portée locale est fusionnée. Ainsi, un CallTarget n'obtiendra pas les valeurs de portée locales modifiées, mais les DependsOnTargets seront supprimés depuis la première cible avant d'entrer dans la seconde cible.

Questions connexes