Freigeben über


Visual Studio C++-Project-Systemerweiterung und Toolsetintegration

Das Visual C++-Projektsystem wird für .vcxproj Dateien verwendet. Sie basiert auf dem Visual Studio Common Project System (CPS)- und bietet zusätzliche, C++-spezifische Erweiterungspunkte für die einfache Integration neuer Toolsets, Buildarchitekturen und Zielplattformen.

Struktur von C++-MSBuild-Zielen

Alle .vcxproj Dateien importieren diese Dateien:

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

Diese Dateien definieren wenig von sich aus. Stattdessen importieren sie andere Dateien basierend auf diesen Eigenschaftswerten:

  • $(ApplicationType)

    Beispiele: Windows Store, Android, Linux

  • $(ApplicationTypeRevision)

    Dies muss eine gültige Versionszeichenfolge im Format major.minor[.build[.revision]] sein.

    Beispiele: 1.0, 10.0.0.0

  • $(Platform)

    Die Buildarchitektur, die aus historischen Gründen als „Platform“ bezeichnet wird.

    Beispiele: Win32, x86, x64, ARM

  • $(PlatformToolset)

    Beispiele: v140, v141, v141_xp, llvm

Diese Eigenschaftswerte geben Ordnernamen unter dem $(VCTargetsPath) Stammordner an:

$(VCTargetsPath)\
    Anwendungstyp\
        $(ApplicationType)\
            $(ApplicationTypeRevision)\
                Plattformen\
                    $(Platform)\
                        PlatformToolsets\
                            $(PlatformToolset)
    Plattformen\
        $(Platform)\
            PlatformToolsets\
                $(PlatformToolset)

Der ordner $(VCTargetsPath)\Platforms\ wird verwendet, wenn $(ApplicationType) leer ist, für Windows-Desktopprojekte.

Hinzufügen eines neuen Plattformtoolsets

Wenn Sie ein neues Toolset hinzufügen möchten, z. B. „MyToolset“ für die vorhandene Win32-Plattform, erstellen Sie unter $(VCTargetsPath)$(VCTargetsPath)\Platforms\Win32\PlatformToolsets\ den Ordner MyToolset, und erstellen Sie darin die Dateien Toolset.props und Toolset.targets.

Jeder Ordnername unter PlatformToolsets wird im Dialogfeld Projekteigenschaften als verfügbares Platform Toolset für die angegebene Plattform angezeigt, wie hier gezeigt:

Die Eigenschaft „PlatformToolset“ im Dialogfeld „Eigenschaftenseiten“ des Projekts

Erstellen Sie ähnliche MyToolset- Ordner und Toolset.props und Toolset.targets Dateien in jedem vorhandenen Plattformordner, den dieses Toolset unterstützt.

Hinzufügen einer neuen Plattform

Um eine neue Plattform hinzuzufügen, z. B. "MyPlatform", erstellen Sie einen MyPlatform- Ordner unter $(VCTargetsPath)\Platforms\, und erstellen Sie Platform.default.props, Platform.propsund Platform.targets Dateien darin. Erstellen Sie außerdem eine $(VCTargetsPath)\Platforms\MyPlatform\PlatformToolsets\ Ordner, und erstellen Sie mindestens ein Toolset darin.

Alle Ordnernamen im Ordner Plattformen für jede $(ApplicationType) und $(ApplicationTypeRevision) werden in der IDE als verfügbare Plattform--Optionen für ein Projekt angezeigt.

Die Option „Neue Plattform“ im Dialogfeld „Neue Projektplattform“

Hinzufügen eines neuen Anwendungstyps

Um einen neuen Anwendungstyp hinzuzufügen, erstellen Sie einen MyApplicationType Ordner unter $(VCTargetsPath)\Application Type\, und erstellen Sie eine Defaults.props Datei darin. Für einen Anwendungstyp ist mindestens eine Überarbeitung erforderlich. Erstellen Sie daher auch einen $(VCTargetsPath)\Application Type\MyApplicationType\1.0 Ordner, und erstellen Sie eine Defaults.props Datei darin. Sie sollten auch einen $(VCTargetsPath)\ApplicationType\MyApplicationType\1.0\Platforms Ordner erstellen und mindestens eine Plattform darin erstellen.

$(ApplicationType) und $(ApplicationTypeRevision) Eigenschaften sind in der Benutzeroberfläche nicht sichtbar. Sie werden in den Projektvorlagen definiert und können nach dem Erstellen des Projekts nicht mehr geändert werden.

Die .vcxproj-Importstruktur

Eine vereinfachte Struktur der Importe für Microsoft C++-Props und Zieldateien sieht wie folgt aus:

$(VCTargetsPath)\Microsoft.Cpp.Default.props
    $(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props
    $(VCTargetsPath)\ImportBefore\Default\*.props
    $(VCTargetsPath)\Application Type\$(ApplicationType)\Default.props
    $(VCTargetsPath)\Application Type\$(ApplicationType)\$(ApplicationTypeRevision)\Default.props
    $(VCTargetsPath)\Anwendungstyp\$(ApplicationType)\$(ApplicationTypeRevision)\Plattformen\$(Platform)\Platform.default.props
    $(VCTargetsPath)\ImportAfter\Default\*.props

Windows-Desktopprojekte definieren $(ApplicationType)nicht, sodass sie nur importieren

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

Wir verwenden die $(_PlatformFolder)-Eigenschaft, um die Speicherorte des Plattformordners $(Platform) zu speichern. Diese Eigenschaft lautet

$(VCTargetsPath)\Plattformen\$(Platform)

für Windows Desktop-Apps und

$(VCTargetsPath)\Anwendungstyp\$(ApplicationType)\$(ApplicationTypeRevision)\Plattformen\$(Platform)

für alle anderen.

Die props-Dateien werden in dieser Reihenfolge importiert:

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

Die Zieldateien werden in dieser Reihenfolge importiert:

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

Wenn Sie einige Standardeigenschaften für Ihr Toolset definieren müssen, können Sie den entsprechenden Ordnern "ImportBefore" und "ImportAfter" Dateien hinzufügen.

Erstellen von Toolset.props- und Toolset.targets-Dateien

Toolset.props und Toolset.targets Dateien haben vollständige Kontrolle darüber, was während eines Builds geschieht, wenn dieses Toolset verwendet wird. Sie können auch die verfügbaren Debugger und einige Aspekte der IDE-Benutzeroberfläche steuern, z. B. den Inhalt im Dialogfeld Eigenschaftenseiten sowie einige andere Aspekte des Projektverhaltens.

Obwohl ein Toolset den gesamten Buildprozess außer Kraft setzen kann, möchten Sie in der Regel nur, dass Das Toolset einige Buildschritte ändern oder hinzufügen oder verschiedene Buildtools als Teil eines vorhandenen Buildprozesses verwenden soll. Um dieses Ziel zu erreichen, gibt es eine Reihe gängiger Props und Zieldateien, die Ihr Toolset importieren kann. Je nachdem, was Ihr Toolset tun soll, können diese Dateien als Importe oder als Beispiele verwendet werden:

  • $(VCTargetsPath)\Microsoft.CppCommon.targets

    Diese Datei definiert die Hauptteile des systemeigenen Buildprozesses und importiert außerdem:

    • $(VCTargetsPath)\Microsoft.CppBuild.targets

    • $(VCTargetsPath)\Microsoft.BuildSteps.targets

    • $(MSBuildToolsPath)\Microsoft.Common.Targets

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

    Legt Standardwerte für Toolsets fest, die die Microsoft-Compiler nutzen und auf Windows abzielen.

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

    Diese Datei bestimmt den Speicherort des Windows SDK und definiert einige wichtige Eigenschaften für Apps für Windows.

Integrieren von toolsetspezifischen Zielen in den C++-Standardbuildprozess

Der standardmäßige C++-Buildprozess wird in Microsoft.CppCommon.targetsdefiniert. Die Ziele dort rufen keine spezifischen Buildtools auf; sie geben die wichtigsten Buildschritte, deren Reihenfolge und Abhängigkeiten an.

Der C++-Build verfügt über drei Hauptschritte, die durch die folgenden Ziele dargestellt werden:

  • BuildGenerateSources

  • BuildCompile

  • BuildLink

Da jeder Buildschritt unabhängig ausgeführt werden kann, können Ziele, die in einem Schritt ausgeführt werden, nicht auf die in den Zielen eines anderen Schritts definierten Elementgruppen und Eigenschaften zurückgreifen. Diese Aufteilung ermöglicht gewisse Optimierungen der Buildleistung. Diese Trennung wird zwar nicht standardmäßig eingesetzt, sollte aber dennoch genutzt werden.

Die Ziele, die innerhalb der einzelnen Schritte ausgeführt werden, werden durch die folgenden Eigenschaften gesteuert:

  • $(BuildGenerateSourcesTargets)

  • $(BuildCompileTargets)

  • $(BeforeBuildLinkTargets)

Jeder Schritt verfügt auch über die Eigenschaften "Before" und "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)" />

Beispiele zu den Zielen, die in den einzelnen Schritten enthalten sind, finden Sie unter Microsoft.CppBuild.targets Datei:

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

Wenn Sie die Ziele wie _ClCompilebetrachten, sehen Sie, dass sie nichts direkt selbst tun, sondern stattdessen von anderen Zielen abhängen, einschließlich ClCompile:

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

ClCompile und andere buildtoolspezifische Ziele werden in Microsoft.CppBuild.targetsals leere Ziele definiert:

<Target Name="ClCompile"/>

Da das Ziel ClCompile leer ist, wenn es nicht von einem Toolset überschrieben wird, wird keine wirkliche Buildaktion ausgeführt. Die Toolsetziele können das ClCompile Ziel außer Kraft setzen, d. h. sie können eine weitere ClCompile Definition enthalten, nachdem sie Microsoft.CppBuild.targetsimportiert haben:

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

Trotz seines Namens, der vor der Implementierung der plattformübergreifenden Unterstützung von Visual Studio festgelegt wurde, muss das Ziel ClCompile nicht CL.exe aufrufen. Sie kann auch Clang, gcc oder andere Compiler aufrufen, indem sie entsprechende MSBuild-Aufgaben verwenden.

Das ClCompile Ziel sollte keine Abhängigkeiten aufweisen, mit Ausnahme des SelectClCompile Ziels, das für den Kompilierungsbefehl für die einzelne Datei in der IDE erforderlich ist.

In Toolsetzielen zu verwendende MSBuild-Aufgaben

Um ein tatsächliches Buildtool aufzurufen, muss das Ziel eine MSBuild-Aufgabe aufrufen. Es gibt eine einfache Exec-Aufgabe, mit der Sie eine auszuführende Befehlszeile angeben können. Jedoch haben Buildtools in der Regel viele Optionen, Eingaben und Ausgaben, die für inkrementelle Builds nachverfolgt werden müssen, sodass spezielle Aufgaben dafür sinnvoll sind. Beispielsweise übersetzt die CL-Aufgabe MSBuild-Eigenschaften in CL.exe Schalter, schreibt sie in eine Antwortdatei und ruft CL.exeauf. Außerdem werden alle Eingabe- und Ausgabedateien für spätere inkrementelle Builds nachverfolgt. Weitere Informationen finden Sie unter Inkrementelle Builds und Prüfung des neuesten Stands.

Microsoft.Cpp.Common.Tasks.dll implementiert die folgenden Aufgaben:

  • BSCMake

  • CL

  • ClangCompile (clang-gcc Schalter)

  • LIB

  • LINK

  • MIDL

  • Mt

  • RC

  • XDCMake

  • CustomBuild (z. B. Exec, aber mit Eingabe- und Ausgabenachverfolgung)

  • SetEnv

  • GetOutOfDateItems

Wenn Sie über ein Tool verfügen, das dieselbe Aktion wie ein vorhandenes Tool ausführt und ähnliche Befehlszeilenoptionen hat (wie clang-cl und CL do), können Sie dieselbe Aufgabe für beide verwenden.

Wenn Sie eine neue Aufgabe für ein Buildtool erstellen müssen, können Sie aus den folgenden Optionen wählen:

  1. Wenn Sie diese Aufgabe selten verwenden oder ein paar Sekunden für Ihren Build keine Rolle spielen, können Sie MSBuild -Inlineaufgaben verwenden:

    • Xaml-Aufgabe (eine benutzerdefinierte Buildregel)

      Ein Beispiel für eine Xaml-Aufgabendeklaration finden Sie unter $(VCTargetsPath)\BuildCustomizations\masm.xmlund für die Verwendung finden Sie unter $(VCTargetsPath)\BuildCustomizations\masm.targets.

    • Codeaufgabe

  2. Wenn Sie eine bessere Aufgabenleistung erzielen möchten oder einfach komplexere Funktionen benötigen, verwenden Sie den regulären MSBuild--Aufgabenerstellungsprozess.

    Wenn nicht alle Eingaben und Ausgaben des Tools in der Befehlszeile aufgeführt sind, wie in den Fällen CL, MIDLund RC, und wenn Sie die automatische Erfassung und Ausgabedateinachverfolgung und TLOG-Dateierstellung benötigen, leiten Sie Ihre Aufgabe von der Microsoft.Build.CPPTasks.TrackedVCToolTask Klasse ab. Derzeit gibt es eine Dokumentation für die Basis-ToolTask Klasse, es gibt keine Beispiele oder Dokumentationen für die Details der TrackedVCToolTask Klasse. Wenn dies vielleicht von besonderem Interesse ist, fügen Sie Ihre Stimme zu einer Anfrage in der Developer Communityhinzu.

Inkrementelle Builds und Prüfung des neuesten Stands

Die standardmäßigen inkrementellen MSBuild-Buildziele verwenden Inputs und Outputs Attribute. Wenn Sie diese angeben, ruft MSBuild das Ziel nur auf, wenn einer der Eingaben einen neueren Zeitstempel als alle Ausgaben aufweist. Da Quelldateien häufig andere Dateien enthalten oder importieren und Buildtools je nach Tooloptionen unterschiedliche Ausgaben erzeugen, ist es schwierig, alle möglichen Eingaben und Ausgaben in MSBuild-Zielen anzugeben.

Um dieses Problem zu verwalten, verwendet der C++-Build eine andere Technik, um inkrementelle Builds zu unterstützen. Die meisten Ziele geben keine Eingaben und Ausgaben an und werden daher immer während des Builds ausgeführt. Die von den Zielen aufgerufenen Aufgaben schreiben Informationen zu allen Eingaben und Ausgaben in tlog-Dateien, die die Erweiterung .tlog haben. Die TLOG-Dateien werden von späteren Builds verwendet, um zu überprüfen, was sich geändert hat und neu erstellt werden muss und was up-to-datum ist. Die .tlog-Dateien sind auch die einzige Quelle für die standardmäßige Prüfung des neuesten Stands des Builds in der IDE.

Um alle Eingaben und Ausgaben zu ermitteln, verwenden systemeigene Toolaufgaben tracker.exe und die FileTracker- Klasse, die von MSBuild bereitgestellt wird.

Microsoft.Build.CPPTasks.Common.dll definiert die öffentliche abstrakte Basisklasse TrackedVCToolTask. Die meisten systemeigenen Toolaufgaben werden von dieser Klasse abgeleitet.

Ab Visual Studio 2017 Update 15.8 können Sie die in Microsoft.Cpp.Common.Tasks.dll implementierte GetOutOfDateItems Aufgabe verwenden, um Tlog-Dateien für benutzerdefinierte Ziele mit bekannten Eingaben und Ausgaben zu erstellen. Alternativ können Sie sie mithilfe der WriteLinesToFile Aufgabe erstellen. Ein Beispiel für das Ziel _WriteMasmTlogs finden Sie in $(VCTargetsPath)\BuildCustomizations\masm.targets.

TLOG-Dateien

Es gibt drei Arten von .Tlog-Dateien: lesen-, schreiben-, und Befehlszeilen-. .tlog-Dateien für das Lesen und Schreiben werden von inkrementellen Builds und von der Prüfung des neuesten Stands in der IDE verwendet. Befehlszeilen-.tlog-Dateien werden nur bei inkrementellen Builds verwendet.

MSBuild stellt diese Hilfsklassen zum Lesen und Schreiben von TLOG-Dateien bereit:

Die FlatTrackingData--Klasse kann verwendet werden, um auf TLOG-Dateien mit Lese- und Schreibzugriff zuzugreifen und Eingaben zu identifizieren, die neuer als Ausgaben sind, oder wenn eine Ausgabe fehlt. Sie wird in der Prüfung des neuesten Stands verwendet.

Befehlszeilen-TLOG-Dateien enthalten Informationen über die im Build verwendeten Befehlszeilen. Sie werden nur für inkrementelle Builds verwendet, nicht up-to-Datumsprüfungen, sodass das interne Format von der MSBuild-Aufgabe bestimmt wird, die sie erzeugt.

TLOG-Format lesen

Read .tlog-Dateien (*.read.*.tlog) enthalten Informationen über Quelldateien und deren Abhängigkeiten.

Ein Caret (^) am Anfang einer Zeile gibt eine oder mehrere Quellen an. Quellen, die dieselben Abhängigkeiten gemeinsam nutzen, werden durch einen vertikalen Balken (|) getrennt.

Abhängigkeitsdateien werden im Anschluss an die Quellen jeweils in einer eigenen Zeile aufgeführt. Alle Dateinamen sind vollständige Pfade.

Angenommen, Ihre Projektquellen befinden sich in F:\test\ConsoleApplication1\ConsoleApplication1. Wenn es in Ihrer Quelldatei, Class1.cpp, die folgenden Include-Anweisungen gibt,

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

dann enthält das CL.read.1.tlog Datei die Quelldatei gefolgt von den beiden Abhängigkeiten:

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

Es ist nicht erforderlich, Dateinamen in Großbuchstaben zu schreiben, aber es ist eine Benutzerfreundlichkeit für einige Tools.

TLOG-Format schreiben

.tlog-Dateien für das Schreiben (*.write.*.tlog) verbinden Quellen und Ausgaben.

Ein Caret (^) am Anfang einer Zeile gibt eine oder mehrere Quellen an. Mehrere Quellen werden durch einen vertikalen Balken (|) getrennt.

Die aus den Quellen erstellten Ausgabedateien sollten nach den Quellen aufgelistet werden, jeweils in einer eigenen Zeile. Alle Dateinamen müssen vollständige Pfade sein.

Zum Beispiel, bei einem einfachen Konsolenanwendungsprojekt, das eine zusätzliche Quelldatei Class1.cpphat, kann die Datei link.write.1.tlog enthalten:

^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

Entwurfszeitbuild

In der IDE verwenden .vcxproj Projekte eine Reihe von MSBuild-Zielen, um zusätzliche Informationen aus dem Projekt abzurufen und Ausgabedateien neu zu generieren. Einige dieser Ziele werden nur in Entwurfszeitbuilds verwendet, viele davon aber sowohl in regulären Builds als auch in Entwurfszeitbuilds.

Allgemeine Informationen zu Entwurfszeitbuilds finden Sie in der CPS-Dokumentation zu Entwurfszeitbuilds. Diese Dokumentation gilt nur teilweise für Visual C++-Projekte.

Die in der Dokumentation zu Entwurfszeitbuilds erwähnten Ziele CompileDesignTime und Compile werden für .vcxproj-Projekte niemals ausgeführt. Visual C++ .vcxproj Projekte verwenden unterschiedliche Entwurfszeitziele, um IntelliSense-Informationen abzurufen.

Entwurfszeitziele für IntelliSense-Informationen

Die in .vcxproj Projekten verwendeten Entwurfszeitziele werden in $(VCTargetsPath)\Microsoft.Cpp.DesignTime.targetsdefiniert.

Das GetClCommandLines Ziel sammelt Compileroptionen für IntelliSense:

<Target
  Name="GetClCommandLines"
  Returns="@(ClCommandLines)"
  DependsOnTargets="$(DesignTimeBuildInitTargets);$(ComputeCompileInputsTargets)">
  • DesignTimeBuildInitTargets – Reine Entwurfszeitziele, die für die Initialisierung des Entwurfszeitbuilds benötigt werden. Unter anderem deaktivieren diese Ziele einige der regulären Buildfunktionen, um die Leistung zu verbessern.

  • ComputeCompileInputsTargets – eine Reihe von Zielen, die Compileroptionen und -elemente ändert. Diese Ziele werden sowohl in Entwurfszeitbuilds als auch in regulären Builds ausgeführt.

Das Ziel ruft die CLCommandLine Aufgabe auf, um die Befehlszeile zu erstellen, die für IntelliSense verwendet werden soll. Trotz seines Namens kann er nicht nur CL-Optionen, sondern auch Clang- und gcc-Optionen verarbeiten. Der Typ der Compilerschalter wird durch die eigenschaft ClangMode gesteuert.

Derzeit verwendet die von der aufgabe CLCommandLine erstellte Befehlszeile immer CL-Schalter (auch im Clang-Modus), da sie für die Analyse des IntelliSense-Moduls einfacher sind.

Wenn Sie ein Ziel hinzufügen, das regulär oder zur Entwurfszeit vor der Kompilierung ausgeführt wird, müssen Sie sicherstellen, dass es nicht die Entwurfszeitbuilds unterbricht oder die Leistung beeinträchtigt. Die einfachste Möglichkeit zum Testen Ihres Ziels besteht darin, eine Entwickler-Eingabeaufforderung zu öffnen und diesen Befehl auszuführen:

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

Dieser Befehl erzeugt ein detailliertes Buildprotokoll, msbuild.log, das eine Leistungszusammenfassung für die Ziele und Aufgaben am Ende enthält.

Verwenden Sie unbedingt Condition ="'$(DesignTimeBuild)' != 'true'" bei allen Vorgängen, die nur für reguläre Builds und nicht für Entwurfszeitbuilds sinnvoll sind.

Entwurfszeitziele, die Quellen generieren

Dieses Feature ist für systemeigene Desktopprojekte standardmäßig deaktiviert und wird derzeit für zwischengespeicherte Projektenicht unterstützt.

Wenn GeneratorTarget Metadaten für ein Projektelement definiert sind, wird das Ziel automatisch ausgeführt, wenn das Projekt geladen wird und wenn die Quelldatei geändert wird.

Um z. B. automatisch .cpp- oder H-Dateien aus XAML-Dateien zu generieren, definieren die $(VSInstallDir)\MSBuild\Microsoft\WindowsXaml\v16.0\*\Microsoft.Windows.UI.Xaml.CPP.Targets Dateien diese Entitäten:

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

Um Task.HostObject zum Abrufen des nicht gespeicherten Inhalts von Quelldateien zu verwenden, sollten die Ziele und die Aufgabe als MsbuildHostObjects- für die angegebenen Projekte in einer pkgdef registriert werden:

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

Visual C++-Projekterweiterung in der Visual Studio-IDE

Das Visual C++-Projektsystem basiert auf dem VS Project Systemund verwendet seine Erweiterbarkeitspunkte. Die Implementierung der Projekthierarchie ist jedoch spezifisch für Visual C++ und nicht basierend auf CPS, sodass die Hierarchieerweiterung auf Projektelemente beschränkt ist.

Seiten mit Projekteigenschaften

Allgemeine Entwurfsinformationen finden Sie unter Framework-Multitargeting für VC++-Projekte.

In einfachen Worten werden die Eigenschaftenseiten, die sie im Dialogfeld Projekteigenschaften für ein C++-Projekt sehen, durch Regel Dateien definiert. Eine Regeldatei gibt einen Satz von Eigenschaften an, die auf einer Eigenschaftenseite angezeigt werden sollen, und wie und wo sie in der Projektdatei gespeichert werden sollen. Regeldateien sind .xml Dateien, die das XAML-Format verwenden. Die typen, die zum Serialisieren verwendet werden, werden in Microsoft.Build.Framework.XamlTypesbeschrieben. Weitere Informationen zur Verwendung von Regeldateien in Projekten finden Sie unter XML-Regeldateien für Eigenschaftenseiten.

Die Regeldateien müssen der PropertyPageSchema Elementgruppe hinzugefügt werden:

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

Context Metadaten beschränkt die Sichtbarkeit der Regel, die auch vom Regeltyp gesteuert wird und einen der folgenden Werte aufweisen kann:

Project | File | PropertySheet

CPS unterstützt andere Werte für den Kontexttyp, werden jedoch nicht in Visual C++-Projekten verwendet.

Wenn die Regel in mehr als einem Kontext sichtbar sein soll, verwenden Sie Semikolons (;), um die Kontextwerte zu trennen, wie hier gezeigt:

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

Regelformat und Haupttypen

Das Regelformat ist einfach, sodass in diesem Abschnitt nur die Attribute beschrieben werden, die sich darauf auswirken, wie die Regel auf der Benutzeroberfläche aussieht.

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

Das attribut PageTemplate definiert, wie die Regel im Dialogfeld Eigenschaftenseiten angezeigt wird. Das Attribut kann einen der folgenden Werte aufweisen:

Attribut Beschreibung
generic Alle Eigenschaften werden auf einer Seite unter Rubrikenüberschriften angezeigt.
Die Regel kann für Project- und PropertySheet Kontexte, aber nicht für Filesichtbar sein.

Beispiel: $(VCTargetsPath)\1033\general.xml
tool Kategorien werden als Unterseiten angezeigt.
Die Regel kann in allen Kontexten sichtbar sein: Project, PropertySheet und File.
Die Regel ist nur dann in Project-Eigenschaften sichtbar, wenn das Projekt Elemente mit der in Rule.DataSourcedefinierten ItemType enthält, es sei denn, der Regelname ist in der ProjectTools Elementgruppe enthalten.

Beispiel: $(VCTargetsPath)\1033\clang.xml
debugger Die Seite wird als Teil der Debugseite angezeigt.
Kategorien werden zurzeit ignoriert.
Der Regelname sollte mit dem ExportDebugger Attribut des Debug Launcher MEF-Objekts übereinstimmen.

Beispiel: $(VCTargetsPath)\1033\debugger_local_windows.xml
benutzerdefiniert Benutzerdefinierte Vorlage. Der Name der Vorlage sollte mit dem ExportPropertyPageUIFactoryProvider Attribut des PropertyPageUIFactoryProvider MEF-Objekts übereinstimmen. Siehe Microsoft.VisualStudio.ProjectSystem.Designers.Properties.IPropertyPageUIFactoryProvider.

Beispiel: $(VCTargetsPath)\1033\userMacros.xml

Wenn für die Regel eine der eigenschaftenrasterbasierten Vorlagen verwendet wird, können diese Erweiterbarkeitspunkte für ihre Eigenschaften verwendet werden:

Erweitern einer Regel

Wenn Sie eine vorhandene Regel verwenden möchten, aber nur wenige Eigenschaften hinzufügen oder entfernen (verbergen) müssen, können Sie eine Erweiterungsregelerstellen.

Außerkraftsetzen einer Regel

Vielleicht möchten Sie, dass ihr Toolset die meisten Standardregeln des Projekts verwendet, aber nur ein oder einige davon ersetzen soll. Angenommen, Sie möchten nur die C/C++-Regel ändern, um verschiedene Compileroptionen anzuzeigen. Sie können eine neue Regel mit demselben Namen und Anzeigenamen wie die vorhandene Regel bereitstellen und sie nach dem Import von Standard-CPP-Zielen in die PropertyPageSchema Elementgruppe einschließen. Im Projekt wird nur eine Regel mit einem bestimmten Namen verwendet, und die letzte regel, die in der PropertyPageSchema Elementgruppe enthalten ist, gewinnt.

Projekteelemente

Die ProjectItemsSchema.xml Datei definiert die werte ContentType und ItemType für Elemente, die als Projektelemente behandelt werden, und definiert FileExtension Elemente, um zu bestimmen, zu welcher Elementgruppe eine neue Datei hinzugefügt wird.

Die ProjectItemsSchema-Standarddatei befindet sich in $(VCTargetsPath)\1033\ProjectItemsSchema.xml. Um sie zu erweitern, müssen Sie eine Schemadatei mit einem neuen Namen erstellen, z. B. 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>

Fügen Sie dann in der Zieldatei Folgendes hinzu:

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

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

Debugger

Der Debugdienst in Visual Studio unterstützt die Erweiterbarkeit für das Debugmodul. Weitere Informationen finden Sie in den folgenden Beispielen:

Um die Debug-Engines und andere Eigenschaften für die Debugsitzung anzugeben, müssen Sie eine Debug Launcher MEF-Komponente implementieren und eine debugger Regel hinzufügen. Ein Beispiel finden Sie in der $(VCTargetsPath)\1033\debugger_local_windows.xml-Datei.

Bereitstellen

.vcxproj-Projekte nutzen die Erweiterbarkeit des Visual Studio-Projektsystems für Deploy Providers.

Prüfung des neuesten Stands des Builds

Standardmäßig müssen für die Prüfung des neuesten Stands des Builds während des Builds für alle Buildeingaben und -ausgaben im Ordner $(TlogLocation) .tlog-Dateien für das Lesen und Schreiben erstellt werden.

Gehen Sie für eine benutzerdefinierte Prüfung des neuesten Stands folgendermaßen vor:

  1. Deaktivieren Sie die Standardmäßige up-to-Datumsprüfung, indem Sie die NoVCDefaultBuildUpToDateCheckProvider-Funktion in der Datei Toolset.targets hinzufügen:

    <ItemGroup>
      <ProjectCapability Include="NoVCDefaultBuildUpToDateCheckProvider" />
    </ItemGroup>
    
  2. Implementieren Sie Ihren eigenen IBuildUpToDateCheckProvider.

Projektupgrade

Standard-Upgrader für .vcxproj-Projekte

Der standardmäßige .vcxproj Projektupgrader ändert die PlatformToolset, ApplicationTypeRevision, MSBuild-Toolset-Version und .NET Framework. Die letzten beiden werden immer in die Standardeinstellungen der Visual Studio-Version geändert, aber PlatformToolset und ApplicationTypeRevision können durch spezielle MSBuild-Eigenschaften gesteuert werden.

Der Upgrader verwendet diese Kriterien, um zu entscheiden, ob ein Projekt aktualisiert werden kann oder nicht:

  1. Für Projekte, die ApplicationType und ApplicationTypeRevisiondefinieren, gibt es einen Ordner mit einer höheren Revisionsnummer als die aktuelle.

  2. Die Eigenschaft _UpgradePlatformToolsetFor_<safe_toolset_name> wird für das aktuelle Toolset definiert, und der Wert ist nicht gleich dem aktuellen Toolset.

    In diesen Eigenschaftennamen stellt <safe_toolset_name> den Toolsetnamen mit allen nicht alphanumerischen Zeichen dar, die durch einen Unterstrich (_) ersetzt werden.

Wenn ein Projekt aktualisiert werden kann, nimmt es an Solution Retargetingteil. Weitere Informationen finden Sie unter IVsTrackProjectRetargeting2.

Wenn Sie Projektnamen im Projektmappen-Explorer ausschmücken möchten, wenn Projekte ein bestimmtes Toolset verwenden, müssen Sie die Eigenschaft _PlatformToolsetShortNameFor_<safe_toolset_name> verwenden.

Beispiele für _UpgradePlatformToolsetFor_<safe_toolset_name>- und _PlatformToolsetShortNameFor_<safe_toolset_name> Eigenschaftendefinitionen finden Sie in der Datei Microsoft.Cpp.Default.props. Beispiele für die Verwendung finden Sie im $(VCTargetPath)\Microsoft.Cpp.Platform.targets Datei.

Benutzerdefinierter Projektupgrader

Um ein benutzerdefiniertes Projektupgraderobjekt zu verwenden, implementieren Sie eine MEF-Komponente, wie hier gezeigt:

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

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

Ihr Code kann das standardmäßige .vcxproj Upgraderobjekt importieren und aufrufen:

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

IProjectRetargetHandler ist in Microsoft.VisualStudio.ProjectSystem.VS.dll definiert und ähnelt IVsRetargetProjectAsync.

Definieren Sie die VCProjectUpgraderObjectName Eigenschaft, um das Projektsystem anweisen, Ihr benutzerdefiniertes Upgraderobjekt zu verwenden:

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

Projektupgrade deaktivieren

Verwenden Sie zum Deaktivieren von Projektupgrades einen NoUpgrade Wert:

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

Project-Cache und Erweiterbarkeit

Um die Leistung beim Arbeiten mit großen C++-Lösungen in Visual Studio 2017 zu verbessern, wurde der Projektcache eingeführt. Sie wird als SQLite-Datenbank implementiert, die mit Projektdaten gefüllt ist und dann verwendet wird, um Projekte zu laden, ohne MSBuild- oder CPS-Projekte in den Arbeitsspeicher zu laden.

Da für .vcxproj Projekte, die aus dem Cache geladen wurden, keine CPS-Objekte vorhanden sind, können die MEF-Komponenten der Erweiterung, die UnconfiguredProject oder ConfiguredProject importieren, nicht erstellt werden. Zur Unterstützung der Erweiterbarkeit wird der Projektcache nicht verwendet, wenn Visual Studio erkennt, ob ein Projekt MEF-Erweiterungen verwendet (oder wahrscheinlich verwendet).

Diese Projekttypen werden immer vollständig geladen und verfügen über CPS-Objekte im Arbeitsspeicher, sodass alle MEF-Erweiterungen für sie erstellt werden:

  • Startprojekte

  • Projekte mit einem benutzerdefinierten Projektupgrader, d. h. mit definierter Eigenschaft VCProjectUpgraderObjectName

  • Projekte, die nicht auf Desktop-Windows ausgerichtet sind, d. h., sie definieren eine ApplicationType-Eigenschaft

  • Projekte mit freigegebenen Elementen (.vcxitems) und Projekte, die durch den Import von .vcxitems-Projekten auf diese verweisen.

Wenn keine dieser Bedingungen erkannt wird, wird ein Projektcache erstellt. Der Cache enthält alle Daten aus dem MSBuild-Projekt, die erforderlich sind, um get Abfragen zu VCProjectEngine Schnittstellen zu beantworten. Dies bedeutet, dass alle Änderungen, die von einer Erweiterung auf der Ebene der MSBuild-Eigenschaften- und Zieldateien vorgenommen werden, in den aus dem Cache geladenen Projekten funktionieren sollten.

Bereitstellen Ihrer Erweiterung

Informationen zum Erstellen von VSIX-Dateien finden Sie unter Shipping Visual Studio Extensions. Informationen zum Hinzufügen von Dateien zu speziellen Installationsspeicherorten, z. B. zum Hinzufügen von Dateien unter $(VCTargetsPath), finden Sie unter Installieren außerhalb des Erweiterungsordners.

Weitere Ressourcen

Das Microsoft Build System (MSBuild) stellt das Buildmodul und das erweiterbare XML-basierte Format für Projektdateien bereit. Sie sollten mit grundlegenden MSBuild-Konzepten und mit der Funktionsweise MSBuild für Visual C++- vertraut sein, um das Visual C++-Projektsystem zu erweitern.

Das Managed Extensibility Framework (MEF) stellt die Erweiterungs-APIs bereit, die von CPS und dem Visual C++-Projektsystem verwendet werden. Eine Übersicht über den Einsatz des MEF durch CPS finden Sie unter CPS und MEF in der VSProjectSystem-Übersicht für MEF.

Sie können das vorhandene Buildsystem anpassen, um Buildschritte oder neue Dateitypen hinzuzufügen. Weitere Informationen finden Sie unter Übersicht über MSBuild (Visual C++) und Arbeiten mit Projekteigenschaften.