Delen via


Uitbreidbaarheid en hulpprogrammasetintegratie van Visual Studio C++ Project-systeem

Het Visual C++-projectsysteem wordt gebruikt voor .vcxproj bestanden. Het is gebaseerd op de CPS- (Visual Studio Common Project System) en biedt aanvullende C++-specifieke uitbreidbaarheidspunten voor eenvoudige integratie van nieuwe toolsets, bouwarchitecturen en doelplatforms.

Structuur van C++ MSBuild-targets

Alle .vcxproj bestanden importeren deze bestanden:

<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

Deze bestanden definiëren weinig zelf. In plaats daarvan importeren ze andere bestanden op basis van deze eigenschapswaarden:

  • $(ApplicationType)

    Voorbeelden: Windows Store, Android, Linux

  • $(ApplicationTypeRevision)

    Dit moet een geldige versieaanduiding zijn, van de vorm "major.minor[.build[.revision]]".

    Voorbeelden: 1.0, 10.0.0.0

  • $(Platform)

    De architectuur van de build, die om historische redenen 'Platform' wordt genoemd.

    Voorbeelden: Win32, x86, x64, ARM

  • $(PlatformToolset)

    Voorbeelden: v140, v141, v141_xp, llvm

Deze eigenschapswaarden geven mapnamen op onder de $(VCTargetsPath) hoofdmap:

$(VCTargetsPath)\
     toepassingstype\
        $(ApplicationType)\
            $(ApplicationTypeRevision)\
                 Platforms\
                    $(Platform)\
                         PlatformToolsets\
                            $(PlatformToolset)
     Platforms\
        $(Platform)\
             PlatformToolsets\
                $(PlatformToolset)

De map $(VCTargetsPath)\Platforms\ wordt gebruikt wanneer $(ApplicationType) leeg is voor Windows-bureaubladprojecten.

Een nieuwe platformhulpprogrammaset toevoegen

Als u een nieuwe toolset wilt toevoegen, bijvoorbeeld 'MyToolset' voor het bestaande Win32-platform, maakt u een map MyToolset onder $(VCTargetsPath)\Platforms\Win32\PlatformToolsets\en maakt u Toolset.props en Toolset.targets bestanden erin.

Elke mapnaam onder PlatformToolsets wordt weergegeven in het dialoogvenster Projecteigenschappen als een beschikbare Platform Toolset voor het opgegeven platform, zoals hier wordt weergegeven:

De eigenschap Platform Toolset in het dialoogvenster Projecteigenschapspagina's

Maak vergelijkbare MyToolset mappen en Toolset.props en Toolset.targets bestanden in elke bestaande platformmap die door deze toolset wordt ondersteund.

Een nieuw platform toevoegen

Als u een nieuw platform wilt toevoegen, bijvoorbeeld 'MyPlatform', maakt u een map MyPlatform onder $(VCTargetsPath)\Platforms\en maakt u Platform.default.props, Platform.propsen Platform.targets-bestanden. Maak ook een map $(VCTargetsPath)\Platforms\MyPlatform\PlatformToolsets\ en maak er ten minste één toolset in.

Alle mapnamen onder de map Platforms voor elke $(ApplicationType) en $(ApplicationTypeRevision) worden in de IDE weergegeven als beschikbare platform keuzes voor een project.

De optie Nieuw platform in het dialoogvenster Nieuw projectplatform

Een nieuw toepassingstype toevoegen

Als u een nieuw toepassingstype wilt toevoegen, maakt u een MyApplicationType map onder $(VCTargetsPath)\Application Type\ en maakt u er een Defaults.props bestand in. Er is ten minste één revisie vereist voor een toepassingstype, dus maak ook een $(VCTargetsPath)\Application Type\MyApplicationType\1.0 map en maak er een Defaults.props bestand in. U moet ook een map $(VCTargetsPath)\ApplicationType\MyApplicationType\1.0\Platforms maken en er minstens één platform in aanmaken.

$(ApplicationType) en $(ApplicationTypeRevision) eigenschappen zijn niet zichtbaar in de gebruikersinterface. Ze worden gedefinieerd in de projectsjablonen en kunnen niet worden gewijzigd nadat het project is gemaakt.

De .vcxproj importstructuur

Een vereenvoudigde boom van imports voor Microsoft C++ props en targetbestanden ziet er als volgt uit:

$(VCTargetsPath) \ Microsoft.Cpp.Default.props
     $(MSBuildExtensionsPath) \ $(MSBuildToolsVersion) \ Microsoft.Common.props
     $(VCTargetsPath) \ ImportBefore\Default\*.props
     $(VCTargetsPath) \ toepassingstype\$(ApplicationType)\Default.props
     $(VCTargetsPath) \ toepassingstype\$(ApplicationType)\$(ApplicationTypeRevision)\Default.props
     $(VCTargetsPath) \ toepassingstype\$(ApplicationType)\$(ApplicationTypeRevision)\Platforms\$(Platform)\Platform.default.props
     $(VCTargetsPath) \ ImportAfter\Default\*.props

Windows-bureaubladprojecten definiëren geen $(ApplicationType), zodat ze alleen importeren

$(VCTargetsPath) \ Microsoft.Cpp.Default.props
     $(MSBuildExtensionsPath) \ $(MSBuildToolsVersion) \ Microsoft.Common.props
     $(VCTargetsPath) \ ImportBefore\Default\*.props
     $(VCTargetsPath) \ Platforms\$(Platform)\Platform.default.props
     $(VCTargetsPath) \ ImportAfter\Default\*.props

We gebruiken de eigenschap $(_PlatformFolder) om de locaties van de $(Platform) platformmap te bewaren. Deze eigenschap is

$(VCTargetsPath) \ Platforms\$(Platform)

voor Windows Desktop-apps en

$(VCTargetsPath) \ toepassingstype\$(ApplicationType)\$(ApplicationTypeRevision)\Platforms\$(Platform)

voor al het andere.

De props-bestanden worden in deze volgorde geïmporteerd:

$(VCTargetsPath) \ Microsoft.Cpp.props
     $(_PlatformFolder) \ Platform.props
         $(VCTargetsPath) \ Microsoft.Cpp.Platform.props
             $(_PlatformFolder) \ ImportBefore\*.eigenschappen
             $(_PlatformFolder) \ PlatformToolsets\$(PlatformToolset)\Toolset.props
             $(_PlatformFolder) \ ImportAfter\*.props

De doelbestanden worden in deze volgorde geïmporteerd:

$(VCTargetsPath) \ Microsoft.Cpp.targets
     $(VCTargetsPath) \ Microsoft.Cpp.Current.targets
         $(_PlatformFolder) \ Platform.targets
             $(VCTargetsPath) \ Microsoft.Cpp.Platform.targets
                 $(_PlatformFolder) \ ImportBefore\*.doelen
                 $(_PlatformFolder) \ PlatformToolsets\$(PlatformToolset)\Toolset.target
                 $(_PlatformFolder) \ ImportAfter\*.doelen

Als u enkele standaardeigenschappen voor uw toolset wilt definiëren, kunt u bestanden toevoegen aan de juiste mappen ImportBefore en ImportAfter.

Maak de bestanden Toolset.props en Toolset.targets

Toolset.props en Toolset.targets bestanden volledige controle hebben over wat er gebeurt tijdens een build wanneer deze toolset wordt gebruikt. Ze kunnen ook de beschikbare foutopsporingsprogramma's beheren, een deel van de gebruikersinterface van IDE, zoals de inhoud in het dialoogvenster eigenschappenpagina's en enkele andere aspecten van projectgedrag.

Hoewel een toolset het hele buildproces kan overschrijven, wilt u meestal alleen dat uw toolset een aantal buildstappen wijzigt of toevoegt of verschillende buildhulpprogramma's gebruikt als onderdeel van een bestaand buildproces. Om dit doel te bereiken, zijn er een aantal gebruikelijke hulpprogramma's en doelbestanden die uw toolset kan importeren. Afhankelijk van wat u wilt dat uw toolset doet, kunnen deze bestanden nuttig zijn om te gebruiken als importbewerkingen of als voorbeelden:

  • $(VCTargetsPath) \ Microsoft.CppCommon.targets

    Dit bestand definieert de belangrijkste onderdelen van het systeemeigen buildproces en importeert ook:

    • $(VCTargetsPath) \ Microsoft.CppBuild.targets

    • $(VCTargetsPath) \ Microsoft.BuildSteps.targets

    • $(MSBuildToolsPath) \ Microsoft.Common.Targets

  • $(VCTargetsPath) \ Microsoft.Cpp.Common.props

    Hiermee worden de standaardwaarden ingesteld voor hulpprogramma's die gebruikmaken van de Microsoft-compilers en Windows als doelbesturingssysteem hebben.

  • $(VCTargetsPath) \ Microsoft.Cpp.WindowsSDK.props

    Dit bestand bepaalt de Locatie van de Windows SDK en definieert enkele belangrijke eigenschappen voor apps die gericht zijn op Windows.

Hulpprogrammasetspecifieke doelen integreren met het standaard C++-buildproces

Het standaard C++-buildproces wordt gedefinieerd in Microsoft.CppCommon.targets. De doelen die er zijn, roepen geen specifieke buildhulpprogramma's aan; ze geven de belangrijkste buildstappen, hun volgorde en afhankelijkheden op.

De C++-build heeft drie hoofdstappen, die worden vertegenwoordigd door de volgende doelen:

  • BuildGenerateSources

  • BuildCompile

  • BuildLink

Omdat elke buildstap onafhankelijk kan worden uitgevoerd, kunnen doelen die in één stap worden uitgevoerd, niet afhankelijk zijn van de itemgroepen en eigenschappen die zijn gedefinieerd in de doelen die als onderdeel van een andere stap worden uitgevoerd. Met deze divisie kunt u bepaalde optimalisaties voor buildprestaties uitvoeren. Hoewel het niet standaard wordt gebruikt, wordt u nog steeds aangemoedigd om deze scheiding te respecteren.

De doelen die binnen elke stap worden uitgevoerd, worden beheerd door deze eigenschappen:

  • $(BuildGenerateSourcesTargets)

  • $(BuildCompileTargets)

  • $(BeforeBuildLinkTargets)

Elke stap heeft ook de eigenschappen Before en 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)" />

Zie het bestand Microsoft.CppBuild.targets voor voorbeelden van de doelen die zijn opgenomen in elke stap:

<BuildCompileTargets Condition="'$(ConfigurationType)'\!='Utility'">
  $(BuildCompileTargets);
  _ClCompile;
  _ResGen;
  _ResourceCompile;
  $(BuildLibTargets);
</BuildCompileTargets>

Als u de doelen bekijkt, zoals _ClCompile, ziet u dat ze niets rechtstreeks zelf doen, maar in plaats daarvan afhankelijk zijn van andere doelen, waaronder ClCompile:

<Target Name="_ClCompile"
  DependsOnTargets="$(BeforeClCompileTargets);$(ComputeCompileInputsTargets);MakeDirsForCl;ClCompile;$(AfterClCompileTargets)" >
</Target>

ClCompile en andere specifiek voor buildtool doelen worden gedefinieerd als lege elementen in Microsoft.CppBuild.targets:

<Target Name="ClCompile"/>

Omdat het ClCompile doel leeg is, tenzij het wordt overschreven door een toolset, wordt er geen echte build-actie uitgevoerd. De hulpprogrammasetdoelen kunnen het ClCompile doel overschrijven, dat wil gezegd, ze kunnen een andere ClCompile definitie bevatten na het importeren van Microsoft.CppBuild.targets:

<Target Name="ClCompile"
  Condition="'@(ClCompile)' != ''"
  DependsOnTargets="SelectClCompile">
  <!-- call some MSBuild tasks -->
</Target>

Ondanks de naam die werd gemaakt voordat Visual Studio platformoverschrijdende ondersteuning implementeerde, hoeft het ClCompile-target CL.exeniet aan te roepen. Het kan ook Clang-, gCC- of andere compilers aanroepen met behulp van de juiste MSBuild-taken.

Het ClCompile doel mag geen afhankelijkheden hebben, behalve het SelectClCompile doel. Dit is vereist voor de compilatieopdracht voor één bestand om in de IDE te kunnen werken.

MSBuild-taken voor gebruik in toolsetdoelen

Als u een echt build-hulpprogramma wilt aanroepen, moet het doel een MSBuild-taak aanroepen. Er is een eenvoudige Exec-taak waarmee u een opdrachtregel kunt opgeven die moet worden uitgevoerd. Build-hulpprogramma's hebben echter meestal veel opties, invoer en uitvoer om bij te houden tijdens incrementele builds, dus het is logischer om specifieke taken voor deze te hebben. De CL taak vertaalt bijvoorbeeld MSBuild-eigenschappen in CL.exe switches, schrijft ze naar een antwoordbestand en roept CL.exeaan. Ook worden alle invoer- en uitvoerbestanden voor latere incrementele builds bijgehouden. Zie voor meer informatie incrementele builds en up-todatumcontroles.

De Microsoft.Cpp.Common.Tasks.dll implementeert deze taken:

  • BSCMake

  • CL

  • ClangCompile (clang-gcc-schakelaars)

  • LIB

  • LINK

  • MIDL

  • Mt

  • RC

  • XDCMake

  • CustomBuild (zoals Exec, maar met invoer- en uitvoertracering)

  • SetEnv

  • GetOutOfDateItems

Als u een hulpprogramma hebt dat dezelfde actie uitvoert als een bestaand hulpprogramma en dat vergelijkbare opdrachtregelopties heeft (zoals clang-cl en CL), kunt u dezelfde taak voor beide gebruiken.

Als u een nieuwe taak voor een build-hulpprogramma moet maken, kunt u kiezen uit de volgende opties:

  1. Als u deze taak zelden gebruikt of als een paar seconden niet van belang zijn voor uw build, kunt u MSBuild-taken inline gebruiken:

    • Xaml-taak (een aangepaste buildregel)

      Zie voor een voorbeeld van een Xaml-taakdeclaratie $(VCTargetsPath)\BuildCustomizations\masm.xmlen zie voor het gebruik $(VCTargetsPath)\BuildCustomizations\masm.targets.

    • code taak

  2. Als u betere taakprestaties wilt of complexere functionaliteit nodig hebt, gebruikt u het reguliere MSBuild taakschrijfproces.

    Als niet alle invoer en uitvoer van het hulpprogramma worden vermeld op de opdrachtregel van het hulpprogramma, zoals in de CL, MIDLen RC gevallen, en als u automatische invoer- en uitvoerbestandstracking en .tlog-bestand wilt maken, moet u uw taak afleiden uit de Microsoft.Build.CPPTasks.TrackedVCToolTask-klasse. Op dit moment is er documentatie voor de basisklasse ToolTask, maar er zijn geen voorbeelden of documentatie voor de details van de TrackedVCToolTask-klasse. Als dit van bijzonder belang is, voegt u uw stem toe aan een verzoek op Developer Community.

Incrementele builds en up-to-datumcontroles

De standaard incrementele MSBuild-builddoelen maken gebruik van Inputs en Outputs kenmerken. Als u deze opgeeft, roept MSBuild het doel alleen aan als een van de invoerwaarden een nieuwere tijdstempel heeft dan alle uitvoer. Omdat bronbestanden vaak andere bestanden bevatten of importeren, en buildhulpprogramma's verschillende uitvoer produceren, afhankelijk van de hulpprogrammaopties, is het moeilijk om alle mogelijke invoer en uitvoer in MSBuild-doelen op te geven.

Voor het beheren van dit probleem gebruikt de C++-build een andere techniek ter ondersteuning van incrementele builds. De meeste doelen geven geen invoer en uitvoer op en worden daarom altijd uitgevoerd tijdens de build. De taken die door doelen worden aangeroepen, schrijven informatie over alle invoer en uitvoer in tlog- bestanden met de extensie .tlog. De .tlog-bestanden worden gebruikt door latere builds om te controleren wat er is gewijzigd en opnieuw moet worden opgebouwd, en wat is up-to-date. De .tlog-bestanden zijn ook de enige bron voor de standaard build up-to-date check in de IDE.

Als u alle invoer en uitvoer wilt bepalen, gebruiken systeemeigen taaktaken tracker.exe en de FileTracker klasse die wordt geleverd door MSBuild.

Microsoft.Build.CPPTasks.Common.dll definieert de TrackedVCToolTask openbare abstracte basisklasse. De meeste systeemeigen hulpprogrammataken zijn afgeleid van deze klasse.

Vanaf Visual Studio 2017 update 15.8 kunt u de GetOutOfDateItems taak die is geïmplementeerd in Microsoft.Cpp.Common.Tasks.dll gebruiken om .tlog-bestanden te produceren voor aangepaste doelen met bekende invoer en uitvoer. U kunt ze ook maken met behulp van de WriteLinesToFile taak. Zie het _WriteMasmTlogs doel in $(VCTargetsPath)\BuildCustomizations\masm.targets als voorbeeld.

.tlog-bestanden

Er zijn drie typen .tlog-bestanden: lezen, schrijven en opdrachtregel. .tlog-bestanden voor lezen en schrijven worden gebruikt door incrementele builds en door de up-to-datumcontrole in de IDE. Command-line .tlog-bestanden worden alleen gebruikt in incrementele builds.

MSBuild biedt deze helperklassen voor het lezen en schrijven van .tlog-bestanden:

De FlatTrackingData-klasse kan worden gebruikt om zowel lees- als schrijf-.tlog-bestanden te openen en invoer te identificeren die nieuwer zijn dan uitvoer, of als er een uitvoer ontbreekt. Deze wordt gebruikt in de up-to-datumcontrole.

TLOG-bestanden met opdrachtregels bevatten informatie over opdrachtregels die in de build worden gebruikt. Ze worden alleen gebruikt voor incrementele builds, niet up-to-datumcontroles, dus de interne indeling wordt bepaald door de MSBuild-taak die ze produceert.

.tlog-indeling lezen

Lees .tlog-bestanden (*.read.*.tlog) bevatten informatie over bronbestanden en de bijbehorende afhankelijkheden.

Een caret (^) aan het begin van een regel geeft een of meer bronnen aan. Bronnen die dezelfde afhankelijkheden delen, worden gescheiden door een verticale balk (|).

Afhankelijkheidsbestanden worden weergegeven na de bronnen, elk op een eigen regel. Alle bestandsnamen zijn volledige paden.

Stel dat uw projectbronnen zijn gevonden in F:\test\ConsoleApplication1\ConsoleApplication1. Als uw bronbestand, Class1.cpp, de volgende includes bevat,

#include "stdafx.h" //precompiled header
#include "Class1.h"

vervolgens bevat het bestand CL.read.1.tlog het bronbestand, gevolgd door de twee afhankelijkheden:

^F:\TEST\CONSOLEAPPLICATION1\CONSOLEAPPLICATION1\CLASS1.CPP
F:\TEST\CONSOLEAPPLICATION1\CONSOLEAPPLICATION1\DEBUG\CONSOLEAPPLICATION1.PCH
F:\TEST\CONSOLEAPPLICATION1\CONSOLEAPPLICATION1\CLASS1.H

Het is niet vereist om bestandsnamen in hoofdletters te schrijven, maar het is handig voor sommige hulpprogramma's.

.tlog-indeling schrijven

Write .tlog (*.write.*.tlog)-bestanden verbinden bronnen en uitvoer.

Een caret (^) aan het begin van een regel geeft een of meer bronnen aan. Meerdere bronnen worden gescheiden door een verticale balk (|).

De uitvoerbestanden die zijn gebouwd op basis van de bronnen, moeten worden vermeld na de bronnen, elk op een eigen regel. Alle bestandsnamen moeten volledige paden zijn.

Voor een eenvoudig ConsoleApplication-project met een extra bronbestand Class1.cppkan het bestand link.write.1.tlog bestand bijvoorbeeld het volgende bevatten:

^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

Build tijdens ontwerpproces

In de IDE gebruiken .vcxproj projecten een set MSBuild-doelen om aanvullende informatie uit het project op te halen en uitvoerbestanden opnieuw te genereren. Sommige van deze targets worden alleen tijdens ontwerpcompilaties gebruikt, maar veel ervan worden zowel in reguliere als in ontwerpcompilaties gebruikt.

Zie de CPS-documentatie voor ontwerptijd-buildsvoor algemene informatie over ontwerptijd-builds. Deze documentatie is slechts gedeeltelijk van toepassing op Visual C++-projecten.

De CompileDesignTime- en Compile-targets die worden genoemd in de documentatie voor builds tijdens het ontwerpen, worden nooit uitgevoerd voor .vcxproj-projecten. Visual C++ .vcxproj projecten gebruiken verschillende ontwerptijddoelen om IntelliSense-informatie op te halen.

Ontwerptijddoelen voor IntelliSense-informatie

De ontwerptijddoelen die in .vcxproj projecten worden gebruikt, worden gedefinieerd in $(VCTargetsPath)\Microsoft.Cpp.DesignTime.targets.

Het GetClCommandLines doel verzamelt compileropties voor IntelliSense:

<Target
  Name="GetClCommandLines"
  Returns="@(ClCommandLines)"
  DependsOnTargets="$(DesignTimeBuildInitTargets);$(ComputeCompileInputsTargets)">
  • DesignTimeBuildInitTargets: doelen alleen voor ontwerptijd, vereist voor de initialisatie van de ontwerptijdbouw. Deze doelen schakelen enkele van de reguliere build functionaliteit uit, onder andere om de prestaties te verbeteren.

  • ComputeCompileInputsTargets: een set doelstellingen waarmee compileropties en items worden aangepast. Deze doelen worden uitgevoerd in zowel ontwerptijd als reguliere builds.

Het doel roept de CLCommandLine taak aan om de opdrachtregel te maken die moet worden gebruikt voor IntelliSense. Ondanks de naam kan het niet alleen CL-opties verwerken, maar ook Clang- en gCC-opties. Het type compilerswitches wordt beheerd door de eigenschap ClangMode.

Op dit moment maakt de opdrachtregel die door de CLCommandLine taak wordt geproduceerd altijd gebruik van CL-switches (zelfs in de Clang-modus), omdat deze eenvoudiger zijn voor de IntelliSense-engine om te parseren.

Als u een target toevoegt dat vóór de compilatie wordt uitgevoerd, ongeacht of het tijdens reguliere of ontwerptijd wordt gedaan, moet u ervoor zorgen dat het ontwerptijd-builds niet onderbreekt of de prestaties beïnvloedt. De eenvoudigste manier om uw doel te testen, is door een opdrachtprompt voor ontwikkelaars te openen en deze opdracht uit te voeren:

msbuild /p:SolutionDir=*solution-directory-with-trailing-backslash*;Configuration=Debug;Platform=Win32;BuildingInsideVisualStudio=true;DesignTimebuild=true /t:\_PerfIntellisenseInfo /v:d /fl /fileloggerparameters:PerformanceSummary \*.vcxproj

Deze opdracht produceert een gedetailleerd buildlogboek, msbuild.log, met een prestatieoverzicht voor de doelen en taken aan het einde.

Zorg ervoor dat u Condition ="'$(DesignTimeBuild)' != 'true'" gebruikt in alle bewerkingen die alleen zinvol zijn voor reguliere builds en niet voor ontwerptijd builds.

Ontwerptijddoelen die bronnen genereren

Deze functie is standaard uitgeschakeld voor systeemeigen bureaubladprojecten en wordt momenteel niet ondersteund voor projecten in de cache.

Als GeneratorTarget metagegevens zijn gedefinieerd voor een projectitem, wordt het doel automatisch uitgevoerd wanneer het project wordt geladen en wanneer het bronbestand wordt gewijzigd.

Als u bijvoorbeeld automatisch .cpp- of .h-bestanden wilt genereren op basis van .xaml-bestanden, definiëren de bestanden $(VSInstallDir)\MSBuild\Microsoft\WindowsXaml\v16.0\*\Microsoft.Windows.UI.Xaml.CPP.Targets deze entiteiten:

<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>

Als u Task.HostObject wilt gebruiken om de niet-opgeslagen inhoud van bronbestanden op te halen, moeten de doelen en taak worden geregistreerd als MsbuildHostObjects voor de opgegeven projecten in een pkgdef:

\[$RootKey$\\Projects\\{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\\MSBuildHostObjects\]
\[$RootKey$\\Projects\\{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\\MSBuildHostObjects\\DesignTimeMarkupCompilationCT;CompileXaml\]
@="{83046B3F-8984-444B-A5D2-8029DEE2DB70}"

Uitbreidbaarheid van Visual C++-projecten in Visual Studio IDE

Het Visual C++-projectsysteem is gebaseerd op de VS Project Systemen maakt gebruik van de uitbreidbaarheidspunten. De implementatie van de projecthiërarchie is echter specifiek voor Visual C++ en niet op basis van CPS, dus hiërarchie-uitbreidbaarheid is beperkt tot projectitems.

Pagina's voor projecteigenschappen

Voor algemene ontwerpinformatie, zie Framework multi-targeting voor VC++-projecten.

In eenvoudige termen worden de eigenschappenpagina's die u ziet in het dialoogvenster Projecteigenschappen voor een C++-project gedefinieerd door regel bestanden. Een regelbestand geeft een set eigenschappen op die moet worden weergegeven op een eigenschappenpagina en hoe en waar ze moeten worden opgeslagen in het projectbestand. Regelbestanden zijn .xml bestanden die de Xaml-indeling gebruiken. De typen die worden gebruikt om ze te serialiseren, worden beschreven in Microsoft.Build.Framework.XamlTypes. Zie XML-regelbestanden voor eigenschappenpagina'svoor meer informatie over het gebruik van regelbestanden in projecten.

De regelbestanden moeten worden toegevoegd aan de PropertyPageSchema itemgroep:

<ItemGroup>
  <PropertyPageSchema Include="$(VCTargetsPath)$(LangID)\general.xml;"/>
  <PropertyPageSchema Include="$(VCTargetsPath)$(LangID)\general_file.xml">
    <Context>File</Context>
  </PropertyPageSchema>
</ItemGroup>

Context de zichtbaarheid van regels wordt beperkt door metagegevens, wat ook wordt gecontroleerd door het regeltype, en kan een van de volgende waarden hebben:

Project | File | PropertySheet

CPS ondersteunt andere waarden voor contexttype, maar worden niet gebruikt in Visual C++-projecten.

Als de regel zichtbaar moet zijn in meer dan één context, gebruikt u puntkomma's (;) om de contextwaarden te scheiden, zoals hier wordt weergegeven:

<PropertyPageSchema Include="$(MyFolder)\MyRule.xml">
  <Context>Project;PropertySheet</Context>
</PropertyPageSchema>

Regelindeling en hoofdtypen

De regelindeling is eenvoudig, dus in deze sectie worden alleen de kenmerken beschreven die van invloed zijn op het uiterlijk van de regel in de gebruikersinterface.

<Rule
  Name="ConfigurationGeneral"
  DisplayName="General"
  PageTemplate="generic"
  Description="General"
  xmlns="http://schemas.microsoft.com/build/2009/properties">

Het kenmerk PageTemplate definieert hoe de regel wordt weergegeven in het dialoogvenster Eigenschappenpagina's. Het kenmerk kan een van deze waarden hebben:

Attribuut Beschrijving
generic Alle eigenschappen worden weergegeven op één pagina onder Categoriekoppen
De regel kan zichtbaar zijn voor contexten Project en PropertySheet, maar niet File.

Voorbeeld: $(VCTargetsPath)\1033-\general.xml
tool Categorieën worden weergegeven als subpagina's.
De regel kan zichtbaar zijn in alle contexten: Project, PropertySheet en File.
De regel is alleen zichtbaar in Projecteigenschappen als het project items bevat met de ItemType gedefinieerd in Rule.DataSource, tenzij de regelnaam is opgenomen in de ProjectTools itemgroep.

Voorbeeld: $(VCTargetsPath)\1033-\clang.xml
debugger De pagina wordt weergegeven als onderdeel van de pagina Foutopsporing.
Categorieën worden momenteel genegeerd.
De regelnaam moet overeenkomen met het ExportDebugger kenmerk van het MEF-object van het startprogramma voor foutopsporing.

Voorbeeld: $(VCTargetsPath)\1033-\debugger_local_windows.xml
aangepaste Aangepaste sjabloon. De naam van de sjabloon moet overeenkomen met het kenmerk ExportPropertyPageUIFactoryProvider van het PropertyPageUIFactoryProvider MEF-object. Zie Microsoft.VisualStudio.ProjectSystem.Designers.Properties.IPropertyPageUIFactoryProvider.

Voorbeeld: $(VCTargetsPath)\1033-\userMacros.xml

Als voor de regel een van de sjablonen op basis van eigenschapsraster wordt gebruikt, kunnen deze uitbreidbaarheidspunten worden gebruikt voor de eigenschappen:

Een regel uitbreiden

Als u een bestaande regel wilt gebruiken, maar slechts een paar eigenschappen wilt toevoegen of verwijderen (dat wil weten, verbergen), kunt u een extensieregel maken.

Een regel overschrijven

Misschien wilt u dat uw toolset de meeste standaardregels voor het project gebruikt, maar om slechts een of meer van deze regels te vervangen. Stel dat u alleen de C/C++-regel wilt wijzigen om verschillende compilerswitches weer te geven. U kunt een nieuwe regel met dezelfde naam en weergavenaam opgeven als de bestaande regel en deze opnemen in de PropertyPageSchema itemgroep na het importeren van standaard-cpp-doelen. Er wordt slechts één regel met een bepaalde naam gebruikt in het project en de laatste regel die is opgenomen in de PropertyPageSchema itemgroep wint.

Projectitems

Het bestand ProjectItemsSchema.xml definieert de ContentType en ItemType waarden voor items die worden behandeld als Projectitems en definieert FileExtension elementen om te bepalen aan welke itemgroep een nieuw bestand wordt toegevoegd.

Het standaardbestand ProjectItemsSchema is te vinden in $(VCTargetsPath)\1033\ProjectItemsSchema.xml. Als u het wilt uitbreiden, moet u een schemabestand maken met een nieuwe naam, zoals 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>

Voeg vervolgens in het doelenbestand het volgende toe:

<ItemGroup>
  <PropertyPageSchema Include="MyProjectItemsSchema.xml"/>
</ItemGroup>

Voorbeeld: $(VCTargetsPath)\BuildCustomizations\masm.xml

Debuggers

De foutopsporingsservice in Visual Studio biedt ondersteuning voor uitbreidbaarheid voor de engine voor foutopsporing. Zie deze voorbeelden voor meer informatie:

Als u de foutopsporingsengines en andere eigenschappen voor de foutopsporingssessie wilt opgeven, moet u een Startprogramma voor foutopsporing implementeren MEF-onderdeel en een debugger-regel toevoegen. Zie het $(VCTargetsPath)\1033\debugger_local_windows.xml-bestand voor een voorbeeld.

Implementeren

.vcxproj-projecten maken gebruik van de uitbreidbaarheid van het Visual Studio Project System voor Deploy-providers.

Build up-To- datumcontrole

Voor de build-up-to-datumcontrole moeten standaard .tlog-bestanden worden gelezen en .tlog-bestanden worden gemaakt in de map $(TlogLocation) tijdens de build voor alle build-invoer en -uitvoer.

Een aangepaste up-to-datumcontrole gebruiken:

  1. Schakel de standaardcontrole up-to-datum uit door de NoVCDefaultBuildUpToDateCheckProvider functionaliteit toe te voegen aan het bestand Toolset.targets:

    <ItemGroup>
      <ProjectCapability Include="NoVCDefaultBuildUpToDateCheckProvider" />
    </ItemGroup>
    
  2. Implementeer uw eigen IBuildUpToDateCheckProvider.

Project-upgrade

Standaard .vcxproj-projectupgradefunctie

De standaard-.vcxproj projectupgraderoutine wijzigt de PlatformToolset, ApplicationTypeRevision, msBuild toolset-versie en .NET Framework. De laatste twee worden altijd gewijzigd in de standaardinstellingen van de Visual Studio-versie, maar PlatformToolset en ApplicationTypeRevision kunnen worden beheerd door speciale MSBuild-eigenschappen.

De upgrader gebruikt deze criteria om te bepalen of een project kan worden bijgewerkt of niet:

  1. Voor projecten die ApplicationType en ApplicationTypeRevisiondefiniëren, is er een map met een hoger revisienummer dan het huidige revisienummer.

  2. De eigenschap _UpgradePlatformToolsetFor_<safe_toolset_name> is gedefinieerd voor de huidige toolset en de waarde is niet gelijk aan de huidige toolset.

    In deze eigenschapsnamen vertegenwoordigt <safe_toolset_name> de naam van de toolset waarbij alle niet-alfanumerieke tekens door een liggend streepje (_) zijn vervangen.

Wanneer een project kan worden bijgewerkt, neemt het deel aan Solution Retargeting. Zie IVsTrackProjectRetargeting2voor meer informatie.

Als u projectnamen in Solution Explorer wilt sieren wanneer projecten een specifieke toolset gebruiken, definieert u een _PlatformToolsetShortNameFor_<safe_toolset_name> eigenschap.

Zie het bestand Microsoft.Cpp.Default.props voor voorbeelden van _UpgradePlatformToolsetFor_<safe_toolset_name>- en _PlatformToolsetShortNameFor_<safe_toolset_name> eigenschapsdefinities. Zie het bestand $(VCTargetPath)\Microsoft.Cpp.Platform.targets voor voorbeelden van gebruik.

Aangepaste projectupgrader

Als u een aangepast projectupgradeobject wilt gebruiken, implementeert u een MEF-onderdeel, zoals hier wordt weergegeven:

/// </summary>
[Export("MyProjectUpgrader", typeof(IProjectRetargetHandler))]
[Export(typeof(IProjectRetargetHandler))]
[ExportMetadata("Name", "MyProjectUpgrader")]
[OrderPrecedence(20)]
[PartMetadata(ProjectCapabilities.Requires, ProjectCapabilities.VisualC)]

internal class MyProjectUpgrader: IProjectRetargetHandler
{
    // ...
}

Uw code kan het standaardobject .vcxproj upgrader importeren en aanroepen:

// ...
[Import("VCDefaultProjectUpgrader")]
// ...
    IProjectRetargetHandler Lazy<IProjectRetargetHandler>
    VCDefaultProjectUpgrader { get; set; }
// ...

IProjectRetargetHandler wordt gedefinieerd in Microsoft.VisualStudio.ProjectSystem.VS.dll en is vergelijkbaar met IVsRetargetProjectAsync.

Definieer de eigenschap VCProjectUpgraderObjectName om het projectsysteem te laten weten dat uw aangepaste upgraderobject moet worden gebruikt:

<PropertyGroup>
  <VCProjectUpgraderObjectName>MyProjectUpgrader</VCProjectUpgraderObjectName>
</PropertyGroup>

Projectupgrade uitschakelen

Gebruik een NoUpgrade-waarde om projectupgrades uit te schakelen:

<PropertyGroup>
  <VCProjectUpgraderObjectName>NoUpgrade</VCProjectUpgraderObjectName>
</PropertyGroup>

Projectcache en uitbreidbaarheid

Om de prestaties te verbeteren bij het werken met grote C++-oplossingen in Visual Studio 2017, is de projectcache geïntroduceerd. Het wordt geïmplementeerd als een SQLite-database die is gevuld met projectgegevens en vervolgens wordt gebruikt om projecten te laden zonder MSBuild- of CPS-projecten in het geheugen te laden.

Omdat er geen CPS-objecten aanwezig zijn voor .vcxproj projecten die zijn geladen vanuit de cache, kunnen de MEF-onderdelen van de extensie die UnconfiguredProject of ConfiguredProject importeren, niet worden gemaakt. Ter ondersteuning van uitbreidbaarheid wordt de projectcache niet gebruikt wanneer Visual Studio detecteert of een project MEF-extensies gebruikt (of waarschijnlijk gebruikt).

Deze projecttypen zijn altijd volledig geladen en hebben CPS-objecten in het geheugen, zodat alle MEF-extensies ervoor worden gemaakt:

  • Opstartprojecten

  • Projecten met een aangepaste projectupgrader, dat wil zeggen, ze definiëren een VCProjectUpgraderObjectName-eigenschap

  • Projecten die niet gericht zijn op Desktop Windows, dat wil zeggen, een ApplicationType-eigenschap definiëren.

  • Projecten voor gedeelde items (.vcxitems) en alle projecten die naar deze projecten verwijzen via import van .vcxitems-projecten.

Als geen van deze voorwaarden wordt gedetecteerd, wordt er een projectcache gemaakt. De cache bevat alle gegevens uit het MSBuild-project dat nodig is om get query's op VCProjectEngine interfaces te beantwoorden. Dit betekent dat alle wijzigingen op het niveau van MSBuild props en targets die door een extensie zijn uitgevoerd, correct moeten werken in projecten die vanuit de cache zijn geladen.

Het verzenden van uw extensie

Zie Shipping Visual Studio Extensionsvoor meer informatie over het maken van VSIX-bestanden. Zie Installeren buiten de map extensiesvoor meer informatie over het toevoegen van bestanden aan speciale installatielocaties, bijvoorbeeld om bestanden toe te voegen onder $(VCTargetsPath).

Aanvullende informatiebronnen

Het Microsoft Build System (MSBuild) biedt de build-engine en de uitbreidbare XML-indeling voor projectbestanden. U moet bekend zijn met de basisconcepten MSBuild en hoe MSBuild voor Visual C++ werkt om het Visual C++-projectsysteem uit te breiden.

Het Managed Extensibility Framework (MEF-) biedt de extensie-API's die worden gebruikt door CPS en het Visual C++-projectsysteem. Zie CPS en MEF in het VSProjectSystem-overzicht van MEFvoor meer informatie over hoe MEF door CPS wordt gebruikt.

U kunt het bestaande buildsysteem aanpassen om buildstappen of nieuwe bestandstypen toe te voegen. Zie MSBuild (Visual C++) Overzicht en Werken met projecteigenschappenvoor meer informatie.