Extensibilité du système de projet C++ de Visual Studio et intégration de l’ensemble d’outils
Le système de projet Visual C++ est utilisé pour .vcxproj fichiers. Elle est basée sur le Visual Studio Common Project System (CPS) et fournit des points d'extensibilité supplémentaires spécifiques à C++ pour faciliter l'intégration de nouveaux ensembles d'outils, de architectures de compilation et de plateformes cibles.
Structure des C++ MSBuild cibles
Tous les fichiers .vcxproj importent ces fichiers :
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
Ces fichiers définissent peu par eux-mêmes. Au lieu de cela, ils importent d’autres fichiers en fonction des valeurs de propriété suivantes :
$(ApplicationType)
Exemples : Windows Store, Android, Linux
$(ApplicationTypeRevision)
Il doit s’agir d’une chaîne de version valide, de la forme major.minor[.build[.revision]].
Exemples : 1.0, 10.0.0.0
$(Platform)
Architecture de construction, nommée « Plateforme » pour des raisons historiques.
Exemples : Win32, x86, x64, ARM
$(PlatformToolset)
Exemples : v140, v141, v141_xp, llvm
Ces valeurs de propriété spécifient les noms de dossiers sous le dossier racine $(VCTargetsPath)
:
$(VCTargetsPath)
\
type d’application\
$(ApplicationType)
\
$(ApplicationTypeRevision)
\
Plateformes \
$(Platform)
\
PlatformToolsets\
$(PlatformToolset)
Plateformes \
$(Platform)
\
PlatformToolsets\
$(PlatformToolset)
Le dossier $(VCTargetsPath)
\Plateformes\ est utilisé lorsque $(ApplicationType)
est vide, pour les projets Windows Desktop.
Ajouter un nouvel ensemble d’outils de plateforme
Pour ajouter un nouvel ensemble d’outils, par exemple, « MyToolset » pour la plateforme Win32 existante, créez un dossier MyToolset sous $(VCTargetsPath)
\Platforms\Win32\PlatformToolsets\, puis créez Toolset.props et Toolset.targets fichiers.
Chaque nom de dossier sous PlatformToolsets apparaît dans la boîte de dialogue propriétés de projet en tant qu’ensemble d’outils de plateforme disponible pour la plateforme spécifiée, comme illustré ici :
Créez des dossiers MyToolset similaires et Toolset.props et Toolset.targets fichiers dans chaque dossier de plateforme existant pris en charge par cet ensemble d’outils.
Ajouter une nouvelle plateforme
Pour ajouter une nouvelle plateforme, par exemple, « MyPlatform », créez un dossier MyPlatform sous $(VCTargetsPath)
\Platforms\, puis créez Platform.default.props, Platform.propset Platform.targets fichiers. Créez également un dossier $(VCTargetsPath)
\Platforms\MyPlatform\PlatformToolsets\ et créez au moins un ensemble d’outils.
Tous les noms de dossiers sous le dossier Plateformes pour chaque $(ApplicationType)
et $(ApplicationTypeRevision)
apparaissent dans l’IDE en tant que choix Platform disponibles pour un projet.
Ajouter un nouveau type d’application
Pour ajouter un nouveau type d’application, créez un dossier MyApplicationType sous $(VCTargetsPath)
\Type d’application\ et créez un fichier Defaults.props. Au moins une révision est requise pour un type d’application. Créez donc également un dossier $(VCTargetsPath)
\Application Type\MyApplicationType\1.0, puis créez un fichier Defaults.props. Vous devez également créer un dossier $(VCTargetsPath)
\ApplicationType\MyApplicationType\1.0\Platforms et y créer au moins une plateforme.
$(ApplicationType)
et les propriétés $(ApplicationTypeRevision)
ne sont pas visibles dans l’interface utilisateur. Ils sont définis dans les modèles de projet et ne peuvent pas être modifiés une fois le projet créé.
Arborescence d’importation .vcxproj
Une arborescence simplifiée des importations pour les fichiers props et cibles de Microsoft C++ ressemble à ceci :
$(VCTargetsPath)
\Microsoft.Cpp.Default.props
$(MSBuildExtensionsPath)
\$(MSBuildToolsVersion)
\Microsoft.Common.props
$(VCTargetsPath)
\ImportBefore\Par défaut\*.propriétés
$(VCTargetsPath)
\type d’application\$(ApplicationType)
\Default.props
$(VCTargetsPath)
\Type d’application\$(ApplicationType)
\$(ApplicationTypeRevision)
\Default.props
$(VCTargetsPath)
\type d’application\$(ApplicationType)
\$(ApplicationTypeRevision)
\Plateformes\$(Platform)
\Platform.default.props
$(VCTargetsPath)
\ImportAfter\Par défaut \*.accessoires
Les projets Windows Desktop ne définissent pas $(ApplicationType)
, donc ils importent uniquement
$(VCTargetsPath)
\Microsoft.Cpp.Default.props
$(MSBuildExtensionsPath)
\$(MSBuildToolsVersion)
\Microsoft.Common.props
$(VCTargetsPath)
\ImportBefore\Par défaut\*.propriétés
$(VCTargetsPath)
\Plateformes\$(Platform)
\Platform.default.props
$(VCTargetsPath)
\ImportAfter\Par défaut \*.accessoires
Nous allons utiliser la propriété $(_PlatformFolder)
pour contenir les emplacements des dossiers de la plateforme $(Platform)
. Cette propriété est
$(VCTargetsPath)
\Plateformes \$(Platform)
pour les applications de bureau Windows et
$(VCTargetsPath)
\Type d'application\$(ApplicationType)
\$(ApplicationTypeRevision)
\Plateformes\$(Platform)
pour tout le reste.
Les fichiers d’accessoires sont importés dans cet ordre :
$(VCTargetsPath)
\Microsoft.Cpp.props
$(_PlatformFolder)
\Platform.props
$(VCTargetsPath)
\Microsoft.Cpp.Platform.props
$(_PlatformFolder)
\ImportBefore\*.accessoires
$(_PlatformFolder)
\PlatformToolsets\$(PlatformToolset)
\Toolset.props
$(_PlatformFolder)
\ImportAfter\*.accessoires
Les fichiers cibles sont importés dans cet ordre :
$(VCTargetsPath)
\Microsoft.Cpp.targets
$(VCTargetsPath)
\Microsoft.Cpp.Current.targets
$(_PlatformFolder)
\Platform.targets
$(VCTargetsPath)
\Microsoft.Cpp.Platform.targets
$(_PlatformFolder)
\ImportBefore\*.cibles
$(_PlatformFolder)
\PlatformToolsets\$(PlatformToolset)
\Toolset.target
$(_PlatformFolder)
\ImportAfter\*.cibles
Si vous devez définir certaines propriétés par défaut pour votre ensemble d’outils, vous pouvez ajouter des fichiers aux dossiers ImportBefore et ImportAfter appropriés.
Créer des fichiers Toolset.props et Toolset.targets
Les fichiers Toolset.props et Toolset.targets ont un contrôle total sur les événements lors d’une compilation lorsqu’un outil est utilisé. Ils peuvent également contrôler les débogueurs disponibles, certaines parties de l'interface utilisateur de l'IDE, tel que le contenu de la boîte de dialogue pages de propriétés, ainsi que d'autres aspects du comportement du projet.
Bien qu’un ensemble d’outils puisse remplacer l’ensemble du processus de génération, vous souhaitez généralement que votre ensemble d’outils modifie ou ajoute des étapes de génération, ou qu’il utilise différents outils de génération dans le cadre d’un processus de génération existant. Pour atteindre cet objectif, il existe plusieurs propriétés et fichiers cibles courants que votre ensemble d’outils peut importer. Selon ce que vous souhaitez que votre ensemble d’outils effectue, ces fichiers peuvent être utiles pour les utiliser en tant qu’importations ou en tant qu’exemples :
$(VCTargetsPath)
\Microsoft.CppCommon.targetsCe fichier définit les parties principales du processus de génération natif et importe également :
$(VCTargetsPath)
\Microsoft.CppBuild.targets$(VCTargetsPath)
\Microsoft.BuildSteps.targets$(MSBuildToolsPath)
\Microsoft.Common.Targets
$(VCTargetsPath)
\Microsoft.Cpp.Common.propsDéfinit les valeurs par défaut pour les ensembles d’outils qui utilisent les compilateurs Microsoft et ciblent Windows.
$(VCTargetsPath)
\Microsoft.Cpp.WindowsSDK.propsCe fichier détermine l’emplacement du Kit de développement logiciel (SDK) Windows et définit certaines propriétés importantes pour les applications ciblant Windows.
Intégrer des cibles spécifiques à l’ensemble d’outils avec le processus de génération C++ par défaut
Le processus de génération C++ par défaut est défini dans Microsoft.CppCommon.targets. Les cibles n'appellent pas d'outils de construction spécifiques ; elles spécifient les principales étapes de construction, leur ordre et leurs dépendances.
La build C++ comporte trois étapes principales, qui sont représentées par les cibles suivantes :
BuildGenerateSources
BuildCompile
BuildLink
Étant donné que chaque étape de génération peut être exécutée indépendamment, les cibles exécutées en une seule étape ne peuvent pas s’appuyer sur les groupes d’éléments et les propriétés définis dans les cibles qui s’exécutent dans le cadre d’une autre étape. Cette division permet certaines optimisations des performances de build. Bien qu’il ne soit pas utilisé par défaut, vous êtes toujours encouragé à respecter cette séparation.
Les cibles exécutées à l’intérieur de chaque étape sont contrôlées par ces propriétés :
$(BuildGenerateSourcesTargets)
$(BuildCompileTargets)
$(BeforeBuildLinkTargets)
Chaque étape possède également les propriétés Before et After.
<Target
Name="_BuildGenerateSourcesAction"
DependsOnTargets="$(CommonBuildOnlyTargets);$(BeforeBuildGenerateSourcesTargets);$(BuildGenerateSourcesTargets);$(AfterBuildGenerateSourcesTargets)" />
<Target
Name="\_BuildCompileAction"
DependsOnTargets="$(CommonBuildOnlyTargets);$(BeforeBuildCompileTargets);$(BuildCompileTargets);$(AfterBuildCompileTargets)" />
<Target
Name="\_BuildLinkAction"
DependsOnTargets="$(CommonBuildOnlyTargets);$(BeforeBuildLinkTargets);$(BuildLinkTargets);$(AfterBuildLinkTargets)" />
Consultez le fichier Microsoft.CppBuild.targets pour obtenir des exemples de cibles incluses dans chaque étape :
<BuildCompileTargets Condition="'$(ConfigurationType)'\!='Utility'">
$(BuildCompileTargets);
_ClCompile;
_ResGen;
_ResourceCompile;
$(BuildLibTargets);
</BuildCompileTargets>
Si vous examinez les cibles, telles que _ClCompile
, vous verrez qu’elles ne font rien directement par eux-mêmes, mais dépendent plutôt d’autres cibles, y compris ClCompile
:
<Target Name="_ClCompile"
DependsOnTargets="$(BeforeClCompileTargets);$(ComputeCompileInputsTargets);MakeDirsForCl;ClCompile;$(AfterClCompileTargets)" >
</Target>
ClCompile
et d’autres cibles spécifiques à l’outil de génération sont définies comme des cibles vides dans Microsoft.CppBuild.targets:
<Target Name="ClCompile"/>
Étant donné que la cible ClCompile
est vide, sauf si elle est remplacée par un ensemble d’outils, aucune action de génération réelle n’est effectuée. Les cibles d’ensemble d’outils peuvent remplacer la cible ClCompile
, autrement dit, elles peuvent contenir une autre définition de ClCompile
après l’importation Microsoft.CppBuild.targets:
<Target Name="ClCompile"
Condition="'@(ClCompile)' != ''"
DependsOnTargets="SelectClCompile">
<!-- call some MSBuild tasks -->
</Target>
Malgré son nom, qui a été créé avant que Visual Studio n’implémente la prise en charge multiplateforme, la cible ClCompile
n’a pas besoin d’appeler CL.exe. Il peut également appeler Clang, gcc ou d’autres compilateurs à l’aide de tâches MSBuild appropriées.
La cible ClCompile
ne doit pas avoir de dépendances, à l’exception de la cible SelectClCompile
, qui est requise pour que la commande de compilation de fichiers unique fonctionne dans l’IDE.
Tâches MSBuild à utiliser dans les cibles des jeux d'outils
Pour appeler un outil de génération réel, la cible doit appeler une tâche MSBuild. Il existe une tâche Exec de base qui vous permet de spécifier une ligne de commande à exécuter. Toutefois, les outils de construction ont généralement de nombreuses options, entrées et sorties à suivre pour les builds incrémentiels, il est donc plus judicieux de leur attribuer des tâches spéciales. Par exemple, la tâche CL
traduit les propriétés MSBuild en commutateurs CL.exe, les écrit dans un fichier réponse et appelle CL.exe. Il effectue également le suivi de tous les fichiers d’entrée et de sortie pour les builds incrémentielles ultérieures. Pour plus d'informations, consultez compilations incrémentielles et up-to vérifications de date.
Le Microsoft.Cpp.Common.Tasks.dll implémente ces tâches :
BSCMake
CL
ClangCompile
(commutateurs clang-gcc)LIB
LINK
MIDL
Mt
RC
XDCMake
CustomBuild
(comme Exec, mais avec le suivi d’entrée et de sortie)SetEnv
GetOutOfDateItems
Si vous avez un outil qui effectue la même action qu’un outil existant et qui a des commutateurs de ligne de commande similaires (comme clang-cl et CL), vous pouvez utiliser la même tâche pour les deux.
Si vous devez créer une tâche pour un outil de génération, vous pouvez choisir parmi les options suivantes :
Si vous utilisez cette tâche rarement, ou si quelques secondes n’ont pas d’importance pour votre build, vous pouvez utiliser des tâches MSBuild « inline » :
Tâche Xaml (règle de génération personnalisée)
Pour obtenir un exemple de déclaration de tâche Xaml, consultez
$(VCTargetsPath)
\BuildCustomizations\masm.xmlet pour son utilisation, consultez$(VCTargetsPath)
\BuildCustomizations\masm.targets.
Si vous souhaitez améliorer les performances des tâches ou avez simplement besoin de fonctionnalités plus complexes, utilisez le processus habituel d'écriture de tâches MSBuild .
Si toutes les entrées et sorties de l’outil ne sont pas répertoriées sur la ligne de commande de l’outil, comme dans l'
CL
,MIDL
et les casRC
, et si vous souhaitez que le suivi automatique des fichiers d’entrée et de sortie et la création de fichiers .tlog, dérivez votre tâche de la classeMicrosoft.Build.CPPTasks.TrackedVCToolTask
. À l’heure actuelle, bien qu’il existe de la documentation pour la classe de base ToolTask, il n’existe aucun exemple ni documentation pour les détails de la classeTrackedVCToolTask
. Si cela présente un intérêt particulier, ajoutez votre voix à une demande sur Communauté du développeur.
Builds incrémentielles et vérifications de up-to-date
Les cibles de build incrémentielle MSBuild par défaut utilisent des attributs Inputs
et Outputs
. Si vous les spécifiez, MSBuild appelle la cible uniquement si l’une des entrées a un horodatage plus récent que toutes les sorties. Étant donné que les fichiers sources incluent ou importent souvent d’autres fichiers et que les outils de génération produisent différentes sorties en fonction des options d’outil, il est difficile de spécifier toutes les entrées et sorties possibles dans les cibles MSBuild.
Pour gérer ce problème, la build C++ utilise une autre technique pour prendre en charge les builds incrémentielles. La plupart des cibles ne spécifient pas d’entrées et de sorties, et par conséquent, s’exécutent toujours pendant la build. Les tâches appelées par les cibles écrivent des informations sur toutes les entrées et sorties dans des fichiers de journal ayant une extension .tlog. Les fichiers .tlog sont utilisés par des builds ultérieures pour vérifier ce qui a changé et doit être reconstruit, et ce qui est up-to-date. Les fichiers .tlog sont également la seule source pour la vérification de la build par défaut up-to-date dans l'IDE.
Pour déterminer toutes les entrées et sorties, les tâches d’outils natives utilisent tracker.exe et la classe FileTracker fournie par MSBuild.
Microsoft.Build.CPPTasks.Common.dll définit la classe de base abstraite publique TrackedVCToolTask
. La plupart des tâches d’outil natives sont dérivées de cette classe.
À compter de Visual Studio 2017 update 15.8, vous pouvez utiliser la tâche de GetOutOfDateItems
implémentée dans Microsoft.Cpp.Common.Tasks.dll pour produire des fichiers .tlog pour des cibles personnalisées avec des entrées et des sorties connues.
Vous pouvez également les créer à l’aide de la tâche WriteLinesToFile
. Consultez la _WriteMasmTlogs
cible dans $(VCTargetsPath)
\BuildCustomizations\masm.targets comme exemple.
Fichiers .tlog
Il existe trois types de fichiers .tlog : lire, écrireet ligne de commande. Les fichiers .tlog de lecture et d'écriture sont utilisés par les compilations incrémentielles et par la vérification de la date up-todans l'IDE. Les fichiers .tlog de ligne de commande sont utilisés uniquement dans les builds incrémentielles.
MSBuild fournit ces classes d’assistance pour lire et écrire des fichiers .tlog :
La classe FlatTrackingData peut être utilisée pour accéder aux fichiers .tlog en lecture et en écriture et identifier les entrées plus récentes que les sorties, ou si une sortie est manquante. Il est utilisé dans la vérification de la date up-to.
Les fichiers .tlog de ligne de commande contiennent des informations sur les lignes de commande utilisées dans la build. Elles sont uniquement utilisées pour les builds incrémentielles, pas pour les vérifications de date up-to, de sorte que le format interne est déterminé par la tâche MSBuild qui les produit.
Lire le format .tlog
Read, les fichiers .tlog (*.read.*.tlog) contiennent des informations sur les fichiers sources et leurs dépendances.
Un caret (^) au début d’une ligne indique une ou plusieurs sources. Les sources qui partagent les mêmes dépendances sont séparées par une barre verticale (|).
Les fichiers de dépendance sont répertoriés après les sources, chacun sur sa propre ligne. Tous les noms de fichiers sont des chemins d’accès complets.
Par exemple, supposons que vos sources de projet se trouvent dans F :\test\ConsoleApplication1\ConsoleApplication1. Si votre fichier source, Class1.cpp, contient ces éléments,
#include "stdafx.h" //precompiled header
#include "Class1.h"
puis le fichier CL.read.1.tlog contient le fichier source suivi de ses deux dépendances :
^F:\TEST\CONSOLEAPPLICATION1\CONSOLEAPPLICATION1\CLASS1.CPP
F:\TEST\CONSOLEAPPLICATION1\CONSOLEAPPLICATION1\DEBUG\CONSOLEAPPLICATION1.PCH
F:\TEST\CONSOLEAPPLICATION1\CONSOLEAPPLICATION1\CLASS1.H
Il n’est pas nécessaire d’écrire des noms de fichiers en majuscules, mais il est pratique pour certains outils.
Écrire le format .tlog
Les fichiers .write .tlog (*.write.*.tlog) connectent les sources et les sorties.
Un caret (^) au début d’une ligne indique une ou plusieurs sources. Plusieurs sources sont séparées par une barre verticale (|).
Les fichiers de sortie générés à partir des sources doivent être répertoriés après les sources, chacun sur sa propre ligne. Tous les noms de fichiers doivent être des chemins complets.
Par exemple, pour un projet ConsoleApplication simple qui a un fichier source supplémentaire Class1.cpp, le fichier link.write.1.tlog peut contenir :
^F:\TEST\CONSOLEAPPLICATION1\CONSOLEAPPLICATION1\DEBUG\CLASS1.OBJ|F:\TEST\CONSOLEAPPLICATION1\CONSOLEAPPLICATION1\DEBUG\CONSOLEAPPLICATION1.OBJ|F:\TEST\CONSOLEAPPLICATION1\CONSOLEAPPLICATION1\DEBUG\STDAFX.OBJ
F:\TEST\CONSOLEAPPLICATION1\DEBUG\CONSOLEAPPLICATION1.ILK
F:\TEST\CONSOLEAPPLICATION1\DEBUG\CONSOLEAPPLICATION1.EXE
F:\TEST\CONSOLEAPPLICATION1\DEBUG\CONSOLEAPPLICATION1.PDB
Compilation à la conception
Dans l’IDE, .vcxproj projets utilisent un ensemble de cibles MSBuild pour obtenir des informations supplémentaires à partir du projet et régénérer les fichiers de sortie. Certaines de ces cibles sont utilisées uniquement dans les builds au temps de conception, mais la plupart d'entre elles sont utilisées à la fois dans les builds réguliers et dans les builds au temps de conception.
Pour obtenir des informations générales sur les builds à l'heure de la conception, consultez la documentation CPS pour builds à l'heure de la conception. Cette documentation ne s’applique qu’en partie aux projets Visual C++.
Les cibles CompileDesignTime
et Compile
mentionnées dans la documentation des builds au moment du design ne s’exécutent jamais pour les projets .vcxproj. Les projets .vcxproj Visual C++ utilisent différentes cibles au moment du design pour obtenir des informations IntelliSense.
Cibles au moment du design pour les informations IntelliSense
Les cibles au moment du design utilisées dans .vcxproj projets sont définies dans $(VCTargetsPath)
\Microsoft.Cpp.DesignTime.targets.
La cible GetClCommandLines
collecte les options du compilateur pour IntelliSense :
<Target
Name="GetClCommandLines"
Returns="@(ClCommandLines)"
DependsOnTargets="$(DesignTimeBuildInitTargets);$(ComputeCompileInputsTargets)">
DesignTimeBuildInitTargets
– cibles au moment du design uniquement, requises pour l’initialisation de build au moment du design. Entre autres, ces cibles désactivent certaines fonctionnalités de build régulières pour améliorer les performances.ComputeCompileInputsTargets
: ensemble de cibles qui modifient les options et les éléments du compilateur. Ces cibles s’exécutent à la fois dans les builds au moment du design et dans les builds régulières.
La cible appelle la tâche CLCommandLine
pour créer la ligne de commande à utiliser pour IntelliSense. Là encore, malgré son nom, il peut gérer non seulement les options CL, mais aussi les options Clang et gcc. Le type des commutateurs du compilateur est contrôlé par la propriété ClangMode
.
Actuellement, la ligne de commande produite par la tâche CLCommandLine
utilise toujours des commutateurs CL (même en mode Clang), car ils sont plus faciles à analyser pour le moteur IntelliSense.
Si vous ajoutez une cible qui s’exécute avant la compilation, qu’elle soit régulière ou au moment du design, assurez-vous qu’elle n’interrompt pas les builds au moment du design ou n’affecte pas les performances. Le moyen le plus simple de tester votre cible consiste à ouvrir une invite de commandes développeur et à exécuter cette commande :
msbuild /p:SolutionDir=*solution-directory-with-trailing-backslash*;Configuration=Debug;Platform=Win32;BuildingInsideVisualStudio=true;DesignTimebuild=true /t:\_PerfIntellisenseInfo /v:d /fl /fileloggerparameters:PerformanceSummary \*.vcxproj
Cette commande produit un journal de génération détaillé, msbuild.log, qui a un résumé des performances pour les cibles et les tâches à la fin.
Veillez à utiliser Condition ="'$(DesignTimeBuild)' != 'true'"
dans toutes les opérations qui ont du sens uniquement pour les constructions régulières et non pour celles pendant la phase de conception.
Cibles pendant la conception qui génèrent des sources
Cette fonctionnalité est désactivée par défaut pour les projets natifs Desktop et n’est actuellement pas prise en charge sur les projets mis en cache.
Si GeneratorTarget
métadonnées sont définies pour un élément de projet, la cible est exécutée automatiquement lorsque le projet est chargé et lorsque le fichier source est modifié.
Par exemple, pour générer automatiquement des fichiers .cpp ou .h à partir de fichiers .xaml, les fichiers $(VSInstallDir)
\MSBuild\Microsoft\WindowsXaml\v16.0\*\Microsoft.Windows.UI.Xaml.CPP.Targets définissent ces entités :
<ItemDefinitionGroup>
<Page>
<GeneratorTarget>DesignTimeMarkupCompilation</GeneratorTarget>
</Page>
<ApplicationDefinition>
<GeneratorTarget>DesignTimeMarkupCompilation</GeneratorTarget>
</ApplicationDefinition>
</ItemDefinitionGroup>
<Target Name="DesignTimeMarkupCompilation">
<!-- BuildingProject is used in Managed builds (always true in Native) -->
<!-- DesignTimeBuild is used in Native builds (always false in Managed) -->
<CallTarget Condition="'$(BuildingProject)' != 'true' Or $(DesignTimeBuild) == 'true'" Targets="DesignTimeMarkupCompilationCT" />
</Target>
Pour utiliser Task.HostObject
pour obtenir le contenu non enregistré des fichiers sources, les cibles et la tâche doivent être inscrites en tant que MsbuildHostObjects pour les projets donnés dans un pkgdef :
\[$RootKey$\\Projects\\{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\\MSBuildHostObjects\]
\[$RootKey$\\Projects\\{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\\MSBuildHostObjects\\DesignTimeMarkupCompilationCT;CompileXaml\]
@="{83046B3F-8984-444B-A5D2-8029DEE2DB70}"
Extensibilité du projet Visual C++ dans l’IDE Visual Studio
Le système de projet Visual C++ est basé sur l'système vs projectet utilise ses points d’extensibilité. Toutefois, l’implémentation de la hiérarchie de projet est spécifique à Visual C++ et non basée sur CPS. L’extensibilité de la hiérarchie est donc limitée aux éléments de projet.
Pages de propriétés du projet
Pour obtenir des informations générales sur la conception, consultez Framework Multi-Targeting for VC++ Projects.
En termes simples, les pages de propriétés que vous voyez dans la boîte de dialogue Propriétés du projet pour un projet C++ sont définies par des fichiers de règles . Un fichier de règle spécifie un ensemble de propriétés à afficher sur une page de propriétés et comment et où ils doivent être enregistrés dans le fichier projet. Les fichiers de règle au format .xml utilisent le format Xaml. Les types utilisés pour les sérialiser sont décrits dans Microsoft.Build.Framework.XamlTypes. Pour plus d’informations sur l’utilisation des fichiers de règle dans les projets, consultez fichiers de règle XML de page de propriétés.
Les fichiers de règle doivent être ajoutés au groupe d’éléments PropertyPageSchema
:
<ItemGroup>
<PropertyPageSchema Include="$(VCTargetsPath)$(LangID)\general.xml;"/>
<PropertyPageSchema Include="$(VCTargetsPath)$(LangID)\general_file.xml">
<Context>File</Context>
</PropertyPageSchema>
</ItemGroup>
Context
limite la visibilité des règles, qui est également contrôlée par type de règle et peut avoir l’une des valeurs suivantes :
Project
| File
| PropertySheet
CPS prend en charge d’autres valeurs pour le type de contexte, mais elles ne sont pas utilisées dans les projets Visual C++.
Si la règle doit être visible dans plusieurs contextes, utilisez des points-virgules (;) pour séparer les valeurs de contexte, comme illustré ici :
<PropertyPageSchema Include="$(MyFolder)\MyRule.xml">
<Context>Project;PropertySheet</Context>
</PropertyPageSchema>
Format de règle et types principaux
Le format de règle est simple. Cette section décrit uniquement les attributs qui affectent l’apparence de la règle dans l’interface utilisateur.
<Rule
Name="ConfigurationGeneral"
DisplayName="General"
PageTemplate="generic"
Description="General"
xmlns="http://schemas.microsoft.com/build/2009/properties">
L’attribut PageTemplate
définit la façon dont la règle est affichée dans la boîte de dialogue des pages de propriétés. L’attribut peut avoir l’une des valeurs suivantes :
Attribut | Description |
---|---|
generic |
Toutes les propriétés sont affichées sur une page sous Titres de catégorie La règle peut être visible pour les contextes Project et PropertySheet , mais pas File .Exemple : $(VCTargetsPath) \1033\general.xml |
tool |
Les catégories sont affichées sous forme de sous-pages. La règle peut être visible dans tous les contextes : Project , PropertySheet et File .La règle est visible dans Propriétés du projet uniquement si le projet comporte des éléments avec le ItemType défini dans Rule.DataSource , sauf si le nom de la règle est inclus dans le groupe d’éléments ProjectTools .Exemple : $(VCTargetsPath) \1033\clang.xml |
debugger |
La page est affichée comme une partie de la page de Débogage. Les catégories sont actuellement ignorées. Le nom de la règle doit correspondre à l’attribut ExportDebugger de l’objet MEF du lanceur de débogage.Exemple : $(VCTargetsPath) \1033\debugger_local_windows.xml |
custom | Modèle personnalisé. Le nom du modèle doit correspondre à l’attribut ExportPropertyPageUIFactoryProvider de l’objet PropertyPageUIFactoryProvider MEF. Consultez Microsoft.VisualStudio.ProjectSystem.Designers.Properties.IPropertyPageUIFactoryProvider.Exemple : $(VCTargetsPath) \1033\userMacros.xml |
Si la règle utilise l’un des modèles Basés sur Property Grid, elle peut utiliser ces points d’extensibilité pour ses propriétés :
Étendre une règle
Si vous souhaitez utiliser une règle existante, mais que vous devez ajouter ou supprimer (autrement dit, masquer) quelques propriétés, vous pouvez créer une règle d’extension .
Remplacer une règle
Peut-être souhaitez-vous que votre ensemble d’outils utilise la plupart des règles par défaut du projet, mais pour remplacer une ou plusieurs d’entre elles. Par exemple, supposons que vous souhaitez uniquement modifier la règle C/C++ pour afficher différents commutateurs du compilateur. Vous pouvez fournir une nouvelle règle portant le même nom et le même nom d’affichage que la règle existante, et l’inclure dans le groupe d’éléments PropertyPageSchema
après l’importation des cibles cpp par défaut. Une seule règle portant un nom donné est utilisée dans le projet, et la dernière règle incluse dans le groupe d’éléments PropertyPageSchema
gagne.
Éléments de projet
Le fichier ProjectItemsSchema.xml définit les valeurs ContentType
et ItemType
pour les éléments traités en tant qu’éléments de projet et définit FileExtension
éléments pour déterminer le groupe d’éléments auquel un nouveau fichier est ajouté.
Le fichier ProjectItemsSchema par défaut se trouve dans $(VCTargetsPath)
\1033\ProjectItemsSchema.xml. Pour l’étendre, vous devez créer un fichier de schéma avec un nouveau nom, tel que MyProjectItemsSchema.xml:
<ProjectSchemaDefinitions xmlns="http://schemas.microsoft.com/build/2009/properties">
<ItemType Name="MyItemType" DisplayName="C/C++ compiler"/>
<ContentType
Name="MyItems"
DisplayName="My items"
ItemType=" MyItemType ">
</ContentType>
<FileExtension Name=".abc" ContentType=" MyItems"/>
</ProjectSchemaDefinitions>
Ensuite, dans le fichier cible, ajoutez :
<ItemGroup>
<PropertyPageSchema Include="MyProjectItemsSchema.xml"/>
</ItemGroup>
Exemple : $(VCTargetsPath)
\BuildCustomizations\masm.xml
Débogueurs
Le service de débogage dans Visual Studio prend en charge l’extensibilité pour le moteur de débogage. Pour plus d’informations, consultez les exemples suivants :
Pour spécifier les moteurs de débogage et d’autres propriétés de la session de débogage, vous devez implémenter un lanceur de débogage composant MEF et ajouter une règle de debugger
. Pour obtenir un exemple, consultez le fichier $(VCTargetsPath)
\1033\debugger_local_windows.xml.
Déployer
Les projets .vcxproj utilisent l'extensibilité Visual Studio Project System pour Déployer des fournisseurs.
Vérifier la mise à jour
Par défaut, la vérification de la vérification de la mise à jour nécessite que des fichiers .tlog soient lus et écrits dans le dossier $(TlogLocation)
pendant la génération pour toutes les entrées et sorties du build.
Pour utiliser une vérification de la mise à jour personnalisée :
Désactivez la vérification de la date par défaut up-to en ajoutant la
NoVCDefaultBuildUpToDateCheckProvider
capacité dans le fichier Toolset.targets :<ItemGroup> <ProjectCapability Include="NoVCDefaultBuildUpToDateCheckProvider" /> </ItemGroup>
Implémentez votre propre IBuildUpToDateCheckProvider.
Mise à niveau du projet
Mise à niveau du projet .vcxproj par défaut
La mise à niveau de projet par défaut .vcxproj modifie la PlatformToolset
, ApplicationTypeRevision
, la version de l’ensemble d’outils MSBuild et .NET Framework. Les deux dernières sont toujours remplacées par les valeurs par défaut de la version de Visual Studio, mais PlatformToolset
et ApplicationTypeRevision
peuvent être contrôlées par des propriétés MSBuild spéciales.
Le upgrader utilise ces critères pour déterminer si un projet peut être mis à niveau ou non :
Pour les projets qui définissent
ApplicationType
etApplicationTypeRevision
, il existe un dossier avec un numéro de révision supérieur à celui actuel.La propriété
_UpgradePlatformToolsetFor_<safe_toolset_name>
est définie pour l’ensemble d’outils actuel et sa valeur n’est pas égale à l’ensemble d’outils actuel.Dans ces noms de propriétés, <safe_toolset_name> représente le nom de l’ensemble d’outils avec tous les caractères non alphanumériques remplacés par un trait de soulignement (_).
Lorsqu'un projet peut être mis à niveau, il participe au reciblage de la solution. Pour plus d’informations, consultez IVsTrackProjectRetargeting2.
Si vous souhaitez orner les noms de projet dans l’Explorateur de solutions lorsque les projets utilisent un ensemble d’outils spécifique, définissez une propriété _PlatformToolsetShortNameFor_<safe_toolset_name>
.
Pour obtenir des exemples de définitions de propriétés _UpgradePlatformToolsetFor_<safe_toolset_name>
et _PlatformToolsetShortNameFor_<safe_toolset_name>
, consultez le fichier microsoft.Cpp.Default.props. Pour obtenir des exemples d’utilisation, consultez le fichier $(VCTargetPath)
\Microsoft.Cpp.Platform.targets.
Mise à niveau de projet personnalisé
Pour utiliser un objet de mise à niveau de projet personnalisé, implémentez un composant MEF, comme illustré ici :
/// </summary>
[Export("MyProjectUpgrader", typeof(IProjectRetargetHandler))]
[Export(typeof(IProjectRetargetHandler))]
[ExportMetadata("Name", "MyProjectUpgrader")]
[OrderPrecedence(20)]
[PartMetadata(ProjectCapabilities.Requires, ProjectCapabilities.VisualC)]
internal class MyProjectUpgrader: IProjectRetargetHandler
{
// ...
}
Votre code peut importer et appeler l’objet de mise à niveau .vcxproj par défaut :
// ...
[Import("VCDefaultProjectUpgrader")]
// ...
IProjectRetargetHandler Lazy<IProjectRetargetHandler>
VCDefaultProjectUpgrader { get; set; }
// ...
IProjectRetargetHandler
est définie dans Microsoft.VisualStudio.ProjectSystem.VS.dll et est similaire à IVsRetargetProjectAsync
.
Définissez la propriété VCProjectUpgraderObjectName
pour indiquer au système de projet d’utiliser votre objet de mise à niveau personnalisé :
<PropertyGroup>
<VCProjectUpgraderObjectName>MyProjectUpgrader</VCProjectUpgraderObjectName>
</PropertyGroup>
Désactiver la mise à niveau du projet
Pour désactiver les mises à niveau de projet, utilisez une valeur NoUpgrade
:
<PropertyGroup>
<VCProjectUpgraderObjectName>NoUpgrade</VCProjectUpgraderObjectName>
</PropertyGroup>
Cache et extensibilité du projet
Pour améliorer les performances lors de l’utilisation de solutions C++ volumineuses dans Visual Studio 2017, le cache de projet a été introduit. Elle est implémentée en tant que base de données SQLite remplie de données de projet, puis utilisée pour charger des projets sans charger des projets MSBuild ou CPS en mémoire.
Étant donné qu’aucun objet CPS n’est présent pour les projets .vcxproj chargés à partir du cache, les composants MEF de l’extension qui importent UnconfiguredProject
ou ConfiguredProject
ne peuvent pas être créés. Pour prendre en charge l’extensibilité, le cache de projet n’est pas utilisé lorsque Visual Studio détecte si un projet utilise (ou est susceptible d’utiliser) des extensions MEF.
Ces types de projet sont toujours entièrement chargés et ont des objets CPS en mémoire, de sorte que toutes les extensions MEF sont créées pour elles :
Projets de démarrage
Projets qui ont un outil de mise à niveau de projet personnalisé, c'est-à-dire, ils définissent une propriété
VCProjectUpgraderObjectName
.Projets qui ne ciblent pas Windows de bureau, autrement dit, ils définissent une propriété
ApplicationType
Projets d’éléments partagés (.vcxitems) et tous les projets qui les référencent par importation de projets .vcxitems.
Si aucune de ces conditions n’est détectée, un cache de projet est créé. Le cache inclut toutes les données du projet MSBuild requis pour répondre aux requêtes get
sur les interfaces VCProjectEngine
. Cela signifie que toutes les modifications au niveau des fichiers de propriétés et de cibles MSBuild effectuées par une extension doivent simplement fonctionner dans les projets chargés à partir du cache.
Expédition de votre extension
Pour plus d’informations sur la création de fichiers VSIX, consultez Shipping Visual Studio Extensions. Pour plus d’informations sur l’ajout de fichiers à des emplacements d’installation spéciaux, par exemple pour ajouter des fichiers sous $(VCTargetsPath)
, consultez Installation en dehors du dossier des extensions.
Ressources additionnelles
Microsoft Build System (MSBuild) fournit le moteur de build et le format XML extensible pour les fichiers projet. Vous devez être familiarisé avec les concepts de base MSBuild et la façon dont MSBuild pour Visual C++ fonctionne afin d’étendre le système de projet Visual C++.
Managed Extensibility Framework (MEF) fournit les API d’extension utilisées par CPS et le système de projet Visual C++. Pour obtenir une vue d'ensemble de la façon dont CPS utilise MEF, consultez CPS et MEF dans l'aperçu VSProjectSystem de MEF.
Vous pouvez personnaliser le système de build existant pour ajouter des étapes de génération ou de nouveaux types de fichiers. Pour plus d’informations, consultez Vue d’ensemble de MSBuild (Visual C++) et Utilisation des propriétés de projet.