web-dev-qa-db-fra.com

Utilisation efficace des propriétés de projet Visual Studio pour plusieurs projets et configurations

J'ai toujours utilisé Visual Studios intégré dans la prise en charge de l'interface graphique pour configurer mes projets, souvent en utilisant des feuilles de propriétés afin que plusieurs projets utilisent un ensemble commun.

L'un de mes principaux reproches consiste à gérer plusieurs projets, configurations et plates-formes. Si vous faites tout simplement avec l'interface graphique principale (cliquez avec le bouton droit sur le projet -> propriétés), cela devient rapidement un gâchis, difficile à maintenir et sujet à des bugs (comme ne pas définir correctement une macro ou utiliser la mauvaise bibliothèque d'exécution, etc.). Gérer le fait que différentes personnes y placent des bibliothèques de dépendances à différents endroits (par exemple, les miennes vivent toutes dans "C:\Libs\[C, C++]\[nom-lib] \"), puis gèrent souvent les différentes versions de ces bibliothèques différemment également (libération, débogage, x86, x64, etc.) est également un gros problème car cela complique considérablement le temps de le configurer sur un nouveau système, et puis il y a des problèmes avec le contrôle de version et en gardant les chemins de chacun séparés. .

Les feuilles de propriétés améliorent un peu cela, mais je ne peux pas avoir une feuille ayant des paramètres distincts pour différentes configurations et plates-formes (les zones de liste déroulante sont grisées), ce qui me permet d'avoir de nombreuses feuilles qui, si elles sont héritées dans le bon ordre, font ce que je veux ( "x86", "x64", "débogage", "version", "commun", "répertoires" (traite le problème de dépendance mentionné précédemment en définissant des macros utilisateur comme BoostX86LibDir), etc.) et s'il est hérité dans le mauvais ordre (par exemple "commun" avant "x64" et "débogage") entraînent des problèmes comme essayer de lier une version de bibliothèque incorrecte ou nommer incorrectement la sortie ...

Ce que je veux, c'est un moyen de gérer toutes ces dépendances dispersées et de configurer un ensemble de "règles" qui sont utilisées par tous mes projets dans la solution, comme nommer une bibliothèque de sortie comme "mylib- [vc90, vc100] - [x86 , x64] [- d] .lib ", sans avoir à faire tout cela pour chaque projet individuel, configuration et combinaison de plate-forme, puis les synchroniser correctement.

Je suis conscient de passer à des systèmes entièrement différents comme CMake qui créent les fichiers nécessaires, mais cela complique ensuite les choses ailleurs en le rendant si simple que des tâches telles que l'ajout d'un nouveau fichier au projet nécessitent ensuite des modifications supplémentaires ailleurs, ce qui n'est pas quelque chose que je suis tout à fait satisfait de l'un ou l'autre, à moins qu'il n'y en ait avec l'intégration VS2010 qui puisse garder une trace de ces sortes de changements.

69
Fire Lancer

Je viens de découvrir quelque chose que je ne pensais pas possible (il n'est pas exposé par l'interface graphique) qui aide à rendre la feuille de propriétés beaucoup plus utile. L'attribut "Condition" de nombreuses balises dans les fichiers de propriétés du projet et il peut également être utilisé dans les fichiers .props!

Je viens de mettre en place ce qui suit comme test et cela a très bien fonctionné et a fait la tâche de 5 (communes, x64, x86, débogage, version) des feuilles de propriétés distinctes!

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.Microsoft.com/developer/msbuild/2003">
  <PropertyGroup Label="UserMacros">
    <!--debug suffix-->
    <DebugSuffix Condition="'$(Configuration)'=='Debug'">-d</DebugSuffix>
    <DebugSuffix Condition="'$(Configuration)'!='Debug'"></DebugSuffix>
    <!--platform-->
    <ShortPlatform Condition="'$(Platform)' == 'Win32'">x86</ShortPlatform>
    <ShortPlatform Condition="'$(Platform)' == 'x64'">x64</ShortPlatform>
    <!--toolset-->
    <Toolset Condition="'$(PlatformToolset)' == 'v90'">vc90</Toolset>
    <Toolset Condition="'$(PlatformToolset)' == 'v100'">vc100</Toolset>
  </PropertyGroup>
  <!--target-->
  <PropertyGroup>
    <TargetName>$(ProjectName)-$(Toolset)-$(ShortPlatform)$(DebugSuffix)</TargetName>
  </PropertyGroup>
</Project>

Le seul problème est que les propriétés de l'interface graphique ne peuvent pas le gérer, un projet qui utilise la feuille de propriétés ci-dessus ne fait que rapporter des valeurs héritées par défaut comme "$ (ProjectName)" pour la cible.

77
Fire Lancer

J'ai fait quelques améliorations, peut être utile à quelqu'un

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.Microsoft.com/developer/msbuild/2003">
  <PropertyGroup Label="UserMacros">
    <!--IsDebug: search for 'Debug' in Configuration-->
    <IsDebug>$([System.Convert]::ToString( $([System.Text.RegularExpressions.Regex]::IsMatch($(Configuration), '[Dd]ebug'))))</IsDebug>

    <!--ShortPlatform-->
    <ShortPlatform Condition="'$(Platform)' == 'Win32'">x86</ShortPlatform>
    <ShortPlatform Condition="'$(Platform)' == 'x64'">x64</ShortPlatform>

    <!--build parameters-->
    <BUILD_DIR>$(registry:HKEY_CURRENT_USER\Software\MyCompany\@BUILD_DIR)</BUILD_DIR>
  </PropertyGroup>

  <Choose>
    <When Condition="$([System.Convert]::ToBoolean($(IsDebug)))">
      <!-- debug macroses -->
      <PropertyGroup Label="UserMacros">
        <MyOutDirBase>Debug</MyOutDirBase>
        <DebugSuffix>-d</DebugSuffix>
      </PropertyGroup>
    </When>
    <Otherwise>
      <!-- other/release macroses -->
      <PropertyGroup Label="UserMacros">
        <MyOutDirBase>Release</MyOutDirBase>
        <DebugSuffix></DebugSuffix>
      </PropertyGroup>
    </Otherwise>
  </Choose>

  <Choose>
    <When Condition="Exists($(BUILD_DIR))">
      <PropertyGroup Label="UserMacros">
        <MyOutDir>$(BUILD_DIR)\Bin\$(MyOutDirBase)_$(ShortPlatform)\</MyOutDir>
        <MyIntDir>$(BUILD_DIR)\Build\$(Configuration)_$(ShortPlatform)_$(PlatformToolset)\$(ProjectGuid)\</MyIntDir>
      </PropertyGroup>
    </When>
    <Otherwise>
      <PropertyGroup Label="UserMacros">
        <MyOutDir>$(SolutionDir)\Bin\$(MyOutDirBase)_$(ShortPlatform)\</MyOutDir>
        <MyIntDir>$(SolutionDir)\Build\$(Configuration)_$(ShortPlatform)_$(PlatformToolset)\$(ProjectGuid)\</MyIntDir>
      </PropertyGroup>
    </Otherwise>
  </Choose>

  <PropertyGroup>
    <OutDir>$(MyOutDir)</OutDir>
    <IntDir>$(MyIntDir)</IntDir>
<!-- some common for projects
    <CharacterSet>Unicode</CharacterSet>
    <LinkIncremental>false</LinkIncremental>
--> 
  </PropertyGroup>
</Project>

s'amuser!

27
lunicon

J'ai eu la même douleur pour le produit de mon entreprise (plus de 200 projets) auparavant. La façon dont je l'ai résolu est de construire une belle hiérarchie des feuilles de propriétés.

Les projets héritent de la feuille de propriétés par son type de sortie, par exemple x64.Debug.Dynamic.Library.vsprops. Ce fichier vsprops hérite simplement d'autres feuilles de propriétés à l'aide de l'attribut InheritedPropertySheets

<VisualStudioPropertySheet
    ProjectType="Visual C++"
    Version="8.00"
    Name="x64.Debug.Dynamic.Binary"
    InheritedPropertySheets=".\Common.vsprops;.\x64.vsprops;.\Debug.vsprops;.\Runtime.Debug.Dynamic.vsprops;.\Output.x64.Library.vsprops"
    >

Vous pouvez également utiliser des variables (c'est-à-dire UserMacro, dont la valeur peut être absolue ou même des variables d'environnement) dans les feuilles de propriétés pour personnaliser beaucoup de choses en fonction de vos besoins. Par exemple, définir une variable BIN dans Debug.vsprops

<UserMacro name="BIN" Value="Debug" />

puis lorsque vous définissez le nom de sortie dans la série de vsprops, disons Output.x64.Library.vsprops

<VisualStudioPropertySheet
    ProjectType="Visual C++"
    Version="8.00"
    OutputDirectory="$(BIN)"
>

La variable $ (BIN) sera étendue à ce qui a été défini (dans ce cas, Debug). Utilisez cette technique, vous pouvez facilement construire une belle hiérarchie de feuilles de propriétés pour répondre à votre demande.

Il y a maintenant une autre chose que vous voudrez peut-être faire: créer vos propres modèles de projet en utilisant votre jeu de feuilles de propriétés. La vraie difficulté est d'imposer une utilisation correcte des modèles et des feuilles de propriétés. Mon expérience personnelle est que même si tout est configuré, quelqu'un oubliera toujours d'utiliser le modèle pour créer de nouveaux projets ...

11
Peon the Great

Il est possible de créer une feuille de propriétés distincte pour chaque configuration. Pour faire ça:

  1. Créer une feuille de propriétés spécifique à la configuration
  2. Ouvrez le gestionnaire de propriétés
  3. Cliquez avec le bouton droit sur configuration (pas sur le projet) que vous souhaitez modifier
  4. Cliquez sur "Ajouter une feuille de propriétés existante" et ajoutez votre feuille

Cela vous évite d'insérer des conditions dans une seule feuille pour plusieurs configurations. Si vous avez des attributs communs que vous souhaitez partager entre les configurations, créez une hiérarchie. La feuille supérieure peut être utilisée dans toutes les configurations et les feuilles imbriquées ne contiendront que l'attribut spécifique à la configuration

5
gogisan

En ce qui concerne la bibliothèque de sortie, vous pouvez sélectionner tous vos projets, puis afficher les pages de propriétés, sélectionner Toutes les configurations, Toutes les plates-formes, puis définir le nom cible sur:

$(ProjectName)-$(PlatformToolset)-$(PlatformShortName)-$(Configuration)

ce qui donnerait une sortie comme mylib-v100-x86-Debug.lib

Nous faisons quelque chose de similaire à cela pour les répertoires de bibliothèques supplémentaires, en utilisant $(PlatformName) et #(Configuration) pour choisir les bons chemins de bibliothèque, bien que cela signifie un peu de déconner avec la configuration initiale des bibliothèques . Par exemple, nous avons boost installé ses bibliothèques sur boost/lib.Win32 ou boost/lib.x64.


En ce qui concerne les bibliothèques et les personnes qui les installent à différents endroits, il existe quelques options. Si vous avez un système de contrôle de source très robuste, vous pouvez simplement tout mettre en contrôle de source, vivant dans un dossier libs à côté de votre source. Cela ne fonctionnera probablement pas si vous utilisez plus de quelques bibliothèques ou si elles sont particulièrement grandes.

L'autre option qui vient à l'esprit est de définir une variable d'environnement sur chaque machine utilisateur qui pointe vers la racine de leur dossier de bibliothèques, par exemple LIB_ROOT=c:\libraries, Et vous pouvez ensuite y accéder dans Visual Studio en tant que $(LIB_ROOT).

4
ngoozeff

Il semble que cela pourrait valoir la peine de vérifier un outil de construction - à ma place, nous utilisons un outil sur mesure qui surveille les fichiers et les projets pour les changements et chiffre les dépendances et l'ordre de compilation. L'ajout d'un nouveau fichier n'est pas un problème - la compilation se fait avec msbuild.

Si je devais compiler plus d'un tas de projets, j'utiliserais quelque chose comme nant: http://nant.sourceforge.net/

0
Rune Andersen