Erweiterbarkeit des Visual Studio C++-Projektsystems und Toolsetintegration
Das Visual C++-Projektsystem wird für .vcxproj-Dateien genutzt. Es basiert auf dem Visual Studio Common Project System (CPS) und liefert zusätzliche, C++-spezifische Erweiterungspunkte für die einfache Integration neuer Toolsets, Buildarchitekturen und Zielplattformen.
Struktur von C++-MSBuild-Zielen
Alle .vcxproj-Dateien importieren die folgenden Dateien:
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
Diese Dateien definieren selbst nur wenig. Sie importieren vielmehr andere Dateien basierend auf diesen Eigenschaftswerten:
$(ApplicationType)
Beispiele: Windows Store, Android, Linux
$(ApplicationTypeRevision)
Das muss eine gültige Versionszeichenfolge der Form major.minor[.build[.revision]] sein.
Beispiele: 1.0, 10.0.0.0
$(Platform)
Die Buildarchitektur, die aus historischen Gründen als „Plattform“ bezeichnet wird.
Beispiele: Win32, x86, x64, ARM
$(PlatformToolset)
Beispiele: v140, v141, v141_xp, llvm
Diese Eigenschaftswerte geben Ordnernamen unter dem Stammordner $(VCTargetsPath)
an:
$(VCTargetsPath)
\
Anwendungstyp\
$(ApplicationType)
\
$(ApplicationTypeRevision)
\
Plattformen\
$(Platform)
\
PlatformToolsets\
$(PlatformToolset)
Plattformen\
$(Platform)
\
PlatformToolsets\
$(PlatformToolset)
Der Ordner $(VCTargetsPath)
\Platforms\ wird für Windows-Desktopprojekte verwendet, wenn $(ApplicationType)
leer ist.
Hinzufügen eines neuen Plattformtoolsets
Zum Hinzufügen eines neuen Toolsets, z. B. „MyToolset“ für die vorhandene Win32-Plattform müssen Sie einen Ordner MyToolset unter $(VCTargetsPath)
\Platforms\Win32\PlatformToolsets\ und dann darin die Dateien Toolset.props und Toolset.targets erstellen.
Jeder Ordnername unter PlatformToolsets wird im Dialog Projekteigenschaften als verfügbares Plattformtoolset für die angegebene Plattform angezeigt, wie hier dargestellt:
Erstellen Sie entsprechende Ordner MyToolset und Dateien Toolset.props Toolset.targets in jedem vorhandenen Plattformordner, den dieses Toolset unterstützt.
Hinzufügen einer neuen Plattform
Zum Hinzufügen einer neuen Plattform, z. B. „MyPlatform“ müssen Sie einen Ordner MyPlatform unter $(VCTargetsPath)
\Platforms\ und dann darin die Dateien Platform.default.props, Platform.props und Platform.targets erstellen. Erstellen Sie außerdem einen Ordner $(VCTargetsPath)
\Platforms\MyPlatform\PlatformToolsets\ und darin mindestens ein Toolset.
Alle Ordnernamen unter dem Ordner Platforms für jeden $(ApplicationType)
und $(ApplicationTypeRevision)
werden in der IDE als verfügbare Auswahlmöglichkeiten für die Plattform für ein Projekt angezeigt.
Hinzufügen eines neuen Anwendungstyps
Zum Hinzufügen eines neuen Anwendungstyp müssen Sie unter einen Ordner MyApplicationType unter $(VCTargetsPath)
\Application Type\ und darin eine Datei Defaults.props erstellen. Für einen Anwendungstyp ist mindestens eine Revision erforderlich. Erstellen Sie daher auch einen Ordner $(VCTargetsPath)
\Application Type\MyApplicationType\1.0 und darin eine Datei Defaults.props. Sie sollten auch einen Ordner $(VCTargetsPath)
\ApplicationType\MyApplicationType\1.0\Platforms und darin mindestens eine Plattform erstellen.
Die Eigenschaften $(ApplicationType)
und $(ApplicationTypeRevision)
sind auf 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++-Eigenschaften- und Zieldateien sieht folgendermaßen 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)
\Application Type\$(ApplicationType)
\$(ApplicationTypeRevision)
\Platforms\$(Platform)
\Platform.default.props
$(VCTargetsPath)
\ImportAfter\Default\*.props
Windows-Desktopprojekte definieren $(ApplicationType)
nicht und importieren deshalb nur
$(VCTargetsPath)
\Microsoft.Cpp.Default.props
$(MSBuildExtensionsPath)
\$(MSBuildToolsVersion)
\Microsoft.Common.props
$(VCTargetsPath)
\ImportBefore\Default\*.props
$(VCTargetsPath)
\Platforms\$(Platform)
\Platform.default.props
$(VCTargetsPath)
\ImportAfter\Default\*.props
Die Eigenschaft $(_PlatformFolder)
dient zum Speichern der $(Platform)
-Plattformordner. Die Eigenschaft ist
$(VCTargetsPath)
\Plattformen\$(Platform)
für Windows-Desktop-Apps und
$(VCTargetsPath)
\Application Type\$(ApplicationType)
\$(ApplicationTypeRevision)
\Platforms\$(Platform)
für alles andere.
Die Eigenschaftendateien werden in diesen Ordner 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 diesen Ordner 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 gewisse Standardeigenschaften für Ihr Toolset definieren müssen, können Sie Dateien zu den entsprechenden Ordnern „ImportBefore“ und „ImportAfter“ hinzufügen.
Schreiben von Toolset.props- and Toolset.targets-Dateien
Toolset.props- und Toolset.targets-Dateien steuern vollständig die Vorgänge während eines Builds bei Verwendung dieses Toolsets. Sie können auch die verfügbaren Debugger, einen Teil der IDE-Benutzeroberfläche, wie z. B. den Inhalt im Dialog Eigenschaftenseiten und gewisse andere Aspekte des Projektverhaltens steuern.
Auch wenn ein Toolset den gesamten Buildprozess außer Kraft setzen kann, werden Sie normalerweise nur wollen, dass das Toolset einige Buildschritte ändert oder hinzufügt oder im Rahmen eines vorhandenen Buildprozesses verschiedene Buildtools verwendet. Zu diesem Zweck gibt es eine Reihe gängiger Eigenschaften- und Zieldateien, die Ihr Toolset importieren kann. Je nach der gewünschten Aufgabe Ihres Toolsets kann es sinnvoll sein, diese Dateien für Importe oder als Beispiele zu verwenden:
$(VCTargetsPath)
\Microsoft.CppCommon.targetsDiese Datei definiert die wichtigsten Teile des nativen Buildprozesses und importiert außerdem:
$(VCTargetsPath)
\Microsoft.CppBuild.targets$(VCTargetsPath)
\Microsoft.BuildSteps.targets$(MSBuildToolsPath)
\Microsoft.Common.Targets
$(VCTargetsPath)
\Microsoft.Cpp.Common.propsLegt Standardwerte für Toolsets fest, die die Microsoft-Compiler und Windows als Ziel verwenden.
$(VCTargetsPath)
\Microsoft.Cpp.WindowsSDK.propsDiese Datei bestimmt den Speicherort des Windows SDK und definiert einige wichtige Eigenschaften von Apps für Windows.
Integrieren toolsetspezifischer Ziele in den standardmäßigen C++-Buildprozess
Der standardmäßige C++-Buildprozess wird in Microsoft.CppCommon.targets definiert. Die Ziele dort rufen keine spezifischen Buildtools auf, sondern geben die wichtigsten Buildschritte, ihre Reihenfolge und ihre Abhängigkeiten an.
Für den C++-Build gibt es drei Hauptschritte, die durch die folgenden Ziele repräsentiert werden:
BuildGenerateSources
BuildCompile
BuildLink
Da jeder Buildschritt eigenständig ausgeführt werden kann, können die in einem Schritt ausgeführten Ziele nicht die Elementgruppen und Eigenschaften heranziehen, die in den als Teil eines anderen Schritts ausgeführten Zielen definiert werden. Diese Aufteilung ermöglicht gewisse Optimierungen der Buildleistung. Diese Trennung wird zwar nicht standardmäßig eingesetzt, sollte aber dennoch genutzt werden.
Die innerhalb jedes Schritts ausgeführten Ziele werden durch die folgenden Eigenschaften gesteuert:
$(BuildGenerateSourcesTargets)
$(BuildCompileTargets)
$(BeforeBuildLinkTargets)
Jeder Schritt hat auch Before- und After-Eigenschaften.
<Target
Name="_BuildGenerateSourcesAction"
DependsOnTargets="$(CommonBuildOnlyTargets);$(BeforeBuildGenerateSourcesTargets);$(BuildGenerateSourcesTargets);$(AfterBuildGenerateSourcesTargets)" />
<Target
Name="\_BuildCompileAction"
DependsOnTargets="$(CommonBuildOnlyTargets);$(BeforeBuildCompileTargets);$(BuildCompileTargets);$(AfterBuildCompileTargets)" />
<Target
Name="\_BuildLinkAction"
DependsOnTargets="$(CommonBuildOnlyTargets);$(BeforeBuildLinkTargets);$(BuildLinkTargets);$(AfterBuildLinkTargets)" />
In der Datei Microsoft.CppBuild.targets finden Sie Beispiele für die in jedem Schritt enthaltenen Ziele:
<BuildCompileTargets Condition="'$(ConfigurationType)'\!='Utility'">
$(BuildCompileTargets);
_ClCompile;
_ResGen;
_ResourceCompile;
$(BuildLibTargets);
</BuildCompileTargets>
Wenn Sie die Ziele wie z. B. _ClCompile
betrachten, sehen Sie, dass sie nichts direkt selbst ausführen, sondern von anderen Zielen wie ClCompile
abhängig sind:
<Target Name="_ClCompile"
DependsOnTargets="$(BeforeClCompileTargets);$(ComputeCompileInputsTargets);MakeDirsForCl;ClCompile;$(AfterClCompileTargets)" >
</Target>
ClCompile
und andere buildtoolspezifische Ziele werden in Microsoft.CppBuild.targets als 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 Ziel ClCompile
überschreiben, d. h., sie können eine andere ClCompile
-Definition enthalten, nachdem Microsoft.CppBuild.targets importiert wurde:
<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. Es kann auch über die entsprechenden MSBuild-Aufgaben Clang, gcc oder andere Compiler aufrufen.
Das Ziel ClCompile
sollte keine Abhängigkeiten haben. Davon ausgenommen ist das Ziel SelectClCompile
, das erforderlich ist, damit der Befehl zum Kompilieren einzelner Dateien in der IDE funktioniert.
In Toolsetzielen zu verwendende MSBuild-Aufgaben
Zum Aufrufen eines tatsächliches Buildtools muss das Ziel eine MSBuild-Aufgabe aufrufen. Es gibt eine grundlegende Exec-Aufgabe, mit der Sie eine auszuführende Befehlszeile angeben können. Buildtools haben jedoch in der Regel viele Optionen, Eingaben und Ausgaben zum Verfolgen inkrementelle Builds, weshalb spezielle Aufgaben dafür sinnvoller sind. Beispielsweise übersetzt die Aufgabe CL
MSBuild-Eigenschaften in CL.exe-Schalter, schreibt sie in eine Antwortdatei und ruft CL.exe auf. Sie verfolgt außerdem alle Eingabe- und Ausgabedateien für spätere inkrementelle Builds. Weitere Informationen finden Sie unter Inkrementelle Builds und Prüfung des neuesten Stands.
Microsoft.Cpp.Common.Tasks.dll implementiert diese Aufgaben:
BSCMake
CL
ClangCompile
(clang-gcc-Schalter)LIB
LINK
MIDL
Mt
RC
XDCMake
CustomBuild
(wie Exec, aber mit Verfolgung der Eingabe und Ausgabe)SetEnv
GetOutOfDateItems
Wenn Sie ein Tool haben, das die gleiche Aktion wie ein vorhandenes Tool ausführt und ähnliche Befehlszeilenschalter hat (wie clang-cl und CL), können Sie für beides die gleiche Aufgabe verwenden.
Wenn Sie eine neue Aufgabe für ein Buildtool erstellen müssen, stehen die folgenden Optionen zur Auswahl:
Wenn Sie diese Aufgabe selten verwenden oder ein paar Sekunden für Ihren Build keine Rolle spielen, können Sie MSBuild-„Inline“-aufgaben verwenden:
Xaml-Aufgabe (eine benutzerdefinierte Buildregel)
Ein Beispiel für eine Xaml-Aufgabendeklaration finden Sie unter
$(VCTargetsPath)
\BuildCustomizations\masm.xml und Informationen zur Verwendung unter$(VCTargetsPath)
\BuildCustomizations\masm.targets.
Wenn Sie eine bessere Aufgabenleistung wünschen oder einfach komplexere Funktionen benötigen, sollten Sie den regulären MSBuild-Prozess zum Schreiben von Aufgaben verwenden.
Wenn nicht alle Eingaben und Ausgaben des Tools in der Befehlszeile aufgeführt sind, wie in den Fällen
CL
,MIDL
undRC
, und wenn Sie die automatische Nachverfolgung von Eingabe- und Ausgabedateien und Erstellung der .tlog-Datei wünschen, sollten Sie Ihre Aufgabe aus der KlasseMicrosoft.Build.CPPTasks.TrackedVCToolTask
ableiten. Derzeit gibt es zwar eine Dokumentation zur Basisklasse ToolTask, aber keine Beispiele und keine Dokumentationen zu den Details der KlasseTrackedVCToolTask
. Wenn das von besonderem Interesse wäre, sollten Sie dies in einer Anfrage in der Entwicklercommunity äußern.
Inkrementelle Builds und Prüfung des neuesten Stands
Die standardmäßigen inkrementellen MSBuild-Buildziele verwenden die Attribute Inputs
und Outputs
. Wenn Sie sie angeben, ruft MSBuild das Ziel nur dann auf, wenn eine der Eingaben einen neueren Zeitstempel als alle Ausgaben hat. 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 bewältigen, setzt der C++-Build eine andere Technik zum Unterstützen inkrementeller Builds ein. Die meisten Ziele geben keine Eingaben und Ausgaben an und werden daher während des Builds immer ausgeführt. Die von den Zielen aufgerufenen Aufgaben schreiben Informationen zu allen Eingaben und Ausgaben in tlog-Dateien, die die Erweiterung .tlog haben. Anhand der .tlog-Dateien können spätere Builds prüfen, was sich geändert hat und neu erstellt werden muss und was auf dem neuesten Stand ist. Die .tlog-Dateien sind auch die einzige Quelle für die standardmäßige Prüfung des neuesten Stands des Builds in der IDE.
Zum Ermitteln aller Eingaben und Ausgaben verwenden native Toolaufgaben tracker.exe und die von MSBuild bereitgestellte FileTracker-Klasse.
Microsoft.Build.CPPTasks.Common.dll definiert die öffentliche abstrakte Basisklasse TrackedVCToolTask
. Die meisten nativen Toolaufgaben sind aus dieser Klasse abgeleitet.
Ab Visual Studio 2017 Update 15.8 können Sie mithilfe der in Microsoft.Cpp.Common.Tasks.dll implementierten Aufgabe GetOutOfDateItems
.tlog-Dateien für benutzerdefinierte Ziele mit bekannten Eingaben und Ausgaben erstellen.
Alternativ können Sie sie auch mithilfe der Aufgabe WriteLinesToFile
erstellen. Ein Beispiel für das Ziel _WriteMasmTlogs
finden Sie in $(VCTargetsPath)
\BuildCustomizations\masm.targets.
.tlog-Dateien
Es gibt drei Typen von .tlog-Dateien: Lesen, Schreiben und Befehlszeile. .tlog-Dateien für das Lesen und Schreiben werden von inkrementellen Builds und von der Prüfung des neuesten Stands in der IDE verwendet. .tlog-Dateien für die Befehlszeile werden nur inkrementellen Builds verwendet.
MSBuild verfügt über die folgenden Hilfsklassen für .tlog-Dateien für das Lesen und Schreiben:
Die Klasse FlatTrackingData kann für den Zugriff auf .tlog-Dateien für das Lesen wie auch für das Schreiben verwendet werden und zum Ermitteln von Eingaben, die neuer sind als Ausgaben, sowie zum Prüfen, ob eine Ausgabe fehlt. Sie wird in der Prüfung des neuesten Stands verwendet.
.tlog-Dateien für die Befehlszeile enthalten Informationen zu den im Build verwendeten Befehlszeilen. Sie werden nur für inkrementelle Builds und nicht für die Prüfung des neuesten Stands verwendet, weshalb das interne Format von der MSBuild-Aufgabe bestimmt wird, die sie erzeugt.
.tlog-Format für das Lesen
.tlog-Dateien für das Lesen (*.read.*.tlog) enthalten Informationen zu Quelldateien und deren Abhängigkeiten.
Ein Caret-Zeichen (^) am Anfang einer Zeile verweist auf eine oder mehrere Quellen. Quellen mit den gleichen Abhängigkeiten werden durch einen senkrechten Strich (|) voneinander 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"
enthält die Datei CL.read.1.tlog die Quelldatei, gefolgt von ihren zwei 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, ist aber für einige Tools zweckmäßig.
.tlog-Format für das Schreiben
.tlog-Dateien für das Schreiben (*.write.*.tlog) verbinden Quellen und Ausgaben.
Ein Caret-Zeichen (^) am Anfang einer Zeile verweist auf eine oder mehrere Quellen. Mehrere Quellen werden durch einen senkrechten Strich (|) voneinander getrennt.
Die aus den Quellen erstellten Ausgabedateien sollten im Anschluss an die Quellen jeweils in einer eigenen Zeile aufgeführt werden. Alle Dateinamen müssen vollständige Pfade sein.
Bei einem einfachen ConsoleApplication-Projekt mit einer zusätzlichen Quelldatei Class1.cpp kann die Datei link.write.1.tlog zum Beispiel Folgendes 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
Entwurfszeit-Build
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 Entwurfszeit-Builds verwendet, viele davon aber sowohl in regulären Builds als auch in Entwurfszeit-Builds.
Allgemeine Informationen zu Entwurfszeit-Builds finden Sie in der CPS-Dokumentation zu Entwurfszeit-Builds. Diese Dokumentation gilt nur teilweise für Visual C++-Projekte.
Die in der Dokumentation zu Entwurfszeit-Builds erwähnten Ziele CompileDesignTime
und Compile
werden für .vcxproj-Projekte niemals ausgeführt. .vcxproj-Projekte in Visual C++ verwenden unterschiedliche Entwurfszeitziele zum Abrufen von IntelliSense-Informationen.
Entwurfszeitziele für IntelliSense-Informationen
Die in .vcxproj-Projekten verwendeten Entwurfszeitziele werden in $(VCTargetsPath)
\Microsoft.Cpp.DesignTime.targets definiert.
Das Ziel GetClCommandLines
erfasst Compileroptionen für IntelliSense:
<Target
Name="GetClCommandLines"
Returns="@(ClCommandLines)"
DependsOnTargets="$(DesignTimeBuildInitTargets);$(ComputeCompileInputsTargets)">
DesignTimeBuildInitTargets
– Reine Entwurfszeitziele, die für die Initialisierung des Entwurfszeit-Builds benötigt werden. Diese Ziele deaktivieren unter anderem einige der regulären Buildfunktionen, um die Leistung zu verbessern.ComputeCompileInputsTargets
– eine Gruppe von Zielen, die Compileroptionen und -elemente ändert. Diese Ziele werden sowohl in Entwurfszeit-Builds als auch in regulären Builds ausgeführt.
Das Ziel ruft die Aufgabe CLCommandLine
auf, um die für IntelliSense zu verwendende Befehlszeile zu erstellen. Trotz ihres Namens kann sie nicht nur CL-Optionen, sondern auch Clang- und gcc-Optionen verarbeiten. Der Typ der Compilerschalter wird von der Eigenschaft ClangMode
gesteuert.
Derzeit verwendet die von der Aufgabe CLCommandLine
erstellte Befehlszeile immer CL-Schalter (auch im Clang-Modus), da sie für die IntelliSense-Engine einfacher zu parsen 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 Entwurfszeit-Builds unterbricht oder die Leistung beeinträchtigt. Die einfachste Möglichkeit zum Testen Ihres Ziels besteht darin, eine Developer-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 erstellt ein detailliertes Buildprotokoll, msbuild.log, mit einer Leistungsübersicht für die Ziele und Aufgaben am Ende.
Verwenden Sie unbedingt Condition ="'$(DesignTimeBuild)' != 'true'"
bei allen Vorgängen, die nur für reguläre Builds und nicht für Entwurfszeit-Builds sinnvoll sind.
Entwurfszeitziele, die Quellen generieren
Dieses Feature ist für native Desktopprojekte standardmäßig deaktiviert und wird für zwischengespeicherte Projekte derzeit nicht unterstützt.
Wenn GeneratorTarget
-Metadaten für ein Projektelement definiert sind, wird das Ziel sowohl beim Laden des Projekts und als auch beim Ändern der Quelldatei automatisch ausgeführt.
Zum automatischen Generieren von .cpp- oder .h-Dateien aus .xaml-Dateien definieren die Dateien $(VSInstallDir)
\MSBuild\Microsoft\WindowsXaml\v16.0\*\Microsoft.Windows.UI.Xaml.CPP.Targets 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>
Damit Task.HostObject
zum Abrufen des nicht gespeicherten Inhalts von Quelldateien verwendet wird, 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}"
Erweiterbarkeit von Visual C++-Projekten in der Visual Studio-IDE
Das Visual C++-Projektsystem basiert auf dem VS-Projektsystem und nutzt dessen Erweiterbarkeitspunkte. Die Implementierung der Projekthierarchie ist jedoch spezifisch für Visual C++ und basiert nicht auf CPS, weshalb die Erweiterbarkeit der Hierarchie auf Projektelemente beschränkt ist.
Seiten mit Projekteigenschaften
Allgemeine Entwurfsinformationen finden Sie unter Framework Multi-Targeting für VC++-Projekte.
Einfach ausgedrückt werden die im Dialog Projekteigenschaften für ein C++-Projekt angezeigten Eigenschaftenseiten durch Regel-Dateien definiert. Eine Regeldatei gibt vor, welcher Satz von Eigenschaften auf einer Eigenschaftenseite angezeigt werden soll und wie und wo sie in der Projektdatei gespeichert werden sollen. Regeldateien sind .xml-Dateien im XAML-Format. Die zum Serialisieren verwendeten Typen werden unter Microsoft.Build.Framework.XamlTypes beschrieben. Weitere Informationen zum Einsatz von Regeldateien in Projekten finden Sie unter XML-Regeldateien für Eigenschaftenseiten.
Die Regeldateien müssen zur Elementgruppe PropertyPageSchema
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änken die Sichtbarkeit der Regel, was ebenfalls vom Regeltyp gesteuert wird, und können einen der folgenden Werte haben:
Project
| File
| PropertySheet
CPS unterstützt weitere Werte für den Kontexttyp, die in Visual C++-Projekten aber nicht verwendet werden.
Wenn die Regel in mehr als einem Kontext sichtbar sein sollte, müssen die Kontextwerte durch Semikolon (;) voneinander getrennt werden, wie hier dargestellt:
<PropertyPageSchema Include="$(MyFolder)\MyRule.xml">
<Context>Project;PropertySheet</Context>
</PropertyPageSchema>
Regelformat und wichtigste Typen
Da das Regelformat unkompliziert ist, werden in diesem Abschnitt nur die Attribute beschrieben, die sich auf das Aussehen der Regel auf der Benutzeroberfläche auswirken.
<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 Dialog Eigenschaftenseiten angezeigt wird. Das Attribut kann einen dieser Werte haben:
Attribute | Beschreibung |
---|---|
generic |
Alle Eigenschaften werden auf einer Seite unter den Kategorieüberschriften angezeigt. Die Regel kann für die Kontexte Project und PropertySheet sichtbar sein, nicht aber für File .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 in den Projekteigenschaften nur dann sichtbar, wenn das Projekt Elemente hat, bei denen ItemType in Rule.DataSource definiert ist, es sei denn, der Regelname ist in der Elementgruppe ProjectTools enthalten.Beispiel: $(VCTargetsPath) \1033\clang.xml |
debugger |
Die Seite wird als Teil der Debugging-Seite angezeigt. Kategorien werden derzeit ignoriert. Der Name der Regel sollte dem Attribut ExportDebugger des MEF-Objekts des Debug-Launchers entsprechen.Beispiel: $(VCTargetsPath) \1033\debugger_local_windows.xml |
custom | Benutzerdefinierte Vorlage. Der Name der Vorlage sollte dem Attribut ExportPropertyPageUIFactoryProvider des MEF-Objekts PropertyPageUIFactoryProvider entsprechen. Siehe Microsoft.VisualStudio.ProjectSystem.Designers.Properties.IPropertyPageUIFactoryProvider.Beispiel: $(VCTargetsPath) \1033\userMacros.xml |
Wenn die Regel eine der auf dem Eigenschaftsraster basierenden Vorlagen verwendet, kann sie diese Erweiterbarkeitspunkte für ihre Eigenschaften verwenden:
Erweitern einer Regel
Wenn Sie eine vorhandene Regel verwenden möchten, aber nur ein paar Eigenschaften hinzufügen oder entfernen (d. h. ausblenden) müssen, können Sie eine Erweiterungsregel erstellen.
Überschreiben einer Regel
Sie möchten vielleicht in ihrem Toolset die meisten Standardregeln des Projekts verwenden und nur eine oder ein paar davon ersetzen. Angenommen, Sie möchten nur die C/C++-Regel dahingehend ändern, dass andere Compilerschalter angezeigt werden. Sie können eine neue Regel mit demselben Namen und Anzeigenamen wie die vorhandene Regel bereitstellen und sie nach dem Import der standardmäßigen ccp-Ziele in die Elementgruppe PropertyPageSchema
aufnehmen. Im Projekt wird nur eine Regel mit einem bestimmten Namen verwendet, und die letzte in die Elementgruppe PropertyPageSchema
aufgenommene Regel trägt den Sieg davon.
Projektelemente
Die Datei ProjectItemsSchema.xml definiert die ContentType
- und ItemType
-Werte 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 standardmäßige Datei ProjectItemsSchema ist unter $(VCTargetsPath)
\1033\ProjectItemsSchema.xml zu finden. Um sie zu erweitern, müssen Sie eine Schemadatei mit einem neuen Namen erstellen, wie 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 die Debug-Engine. Weitere Informationen finden Sie in diesen Beispielen:
Zum Angeben der Debug-Engine und anderer Eigenschaften für die Debugsitzung müssen Sie eine Debug Launcher-MEF-Komponente implementieren und eine debugger
-Regel hinzufügen. Ein Beispiel finden Sie in der Datei $(VCTargetsPath)
\1033\debugger_local_windows.xml.
Bereitstellen
.vcxproj-Projekte nutzen die Erweiterbarkeit des Visual Studio-Projektsystems für Deploy-Anbieter.
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:
Deaktivieren Sie die standardmäßige Prüfung des neuesten Stands, indem Sie die Funktion
NoVCDefaultBuildUpToDateCheckProvider
in der Datei Toolset.targets hinzufügen:<ItemGroup> <ProjectCapability Include="NoVCDefaultBuildUpToDateCheckProvider" /> </ItemGroup>
Implementieren Sie Ihren eigenen IBuildUpToDateCheckProvider.
Projektupgrade
Standardupgrader für .vcxproj-Projekte
Der Standardupgrader für .vcxproj-Projekte ändert PlatformToolset
, ApplicationTypeRevision
, die MSBuild-Toolset-Version und das .NET Framework. Die letzten beiden werden immer in die Standardeinstellungen der Visual Studio-Version geändert, PlatformToolset
und ApplicationTypeRevision
können aber durch spezielle MSBuild-Eigenschaften gesteuert werden.
Der Upgrader entscheidet anhand dieser Kriterien, ob ein Upgrade für ein Projekt möglich ist oder nicht:
Bei Projekten, die
ApplicationType
undApplicationTypeRevision
definieren, gibt es einen Ordner mit einer höheren als der aktuellen Revisionsnummer.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 Namen des Toolsets dar, wobei alle nicht alphanumerischen Zeichen durch einen Unterstrich (_) ersetzt sind.
Wenn für ein Projekt ein Upgrade möglich ist, nimmt es an der Neuzuweisung der Lösung teil. 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 eine Eigenschaft _PlatformToolsetShortNameFor_<safe_toolset_name>
definieren.
Beispiele für Definitionen der Eigenschaften _UpgradePlatformToolsetFor_<safe_toolset_name>
und _PlatformToolsetShortNameFor_<safe_toolset_name>
finden Sie in der Datei Microsoft.Cpp.Default.props. Beispiele für die Verwendung finden Sie in der Datei $(VCTargetPath)
\Microsoft.Cpp.Platform.targets.
Benutzerdefinierter Projektupgrader
Für den Einsatz eines benutzerdefinierten Projektupgraderobjekts müssen Sie eine MEF-Komponente implementieren, wie hier dargestellt:
/// </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 ist vergleichbar mit IVsRetargetProjectAsync
.
Definieren Sie die Eigenschaft VCProjectUpgraderObjectName
, um das Projektsystem anzuweisen, Ihr benutzerdefiniertes Upgraderobjekt zu verwenden:
<PropertyGroup>
<VCProjectUpgraderObjectName>MyProjectUpgrader</VCProjectUpgraderObjectName>
</PropertyGroup>
Deaktivieren des Projektupgrades
Verwenden Sie zum Deaktivieren des Projektupgrades einen NoUpgrade
-Wert:
<PropertyGroup>
<VCProjectUpgraderObjectName>NoUpgrade</VCProjectUpgraderObjectName>
</PropertyGroup>
Projekt-Cache und Erweiterbarkeit
Um beim Arbeiten mit umfangreichen C++-Lösungen in Visual Studio 2017 die Leistung zu verbessern, wurde der Projekt-Cache eingeführt. Er wird als eine mit Projektdaten aufgefüllte SQLite-Datenbank implementiert und dann zum Laden von Projekten eingesetzt, ohne dass MSBuild- oder CPS-Projekte in den Arbeitsspeicher geladen werden.
Da für aus dem Cache geladene VCXPROJ-Projekte 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 Projekt-Cache nicht genutzt, wenn Visual Studio erkennt, dass ein Projekt MEF-Erweiterungen verwendet (oder voraussichtlich verwenden wird).
Diese Projekttypen werden immer vollständig geladen und verfügen über CPS-Objekte im Arbeitsspeicher, sodass alle MEF-Erweiterungen dafür erstellt werden:
Startup-Projekte
Projekte mit einem benutzerdefinierten Projektupgrader, d. h. mit definierter Eigenschaft
VCProjectUpgraderObjectName
Projekte, die nicht Desktop-Windows zum Ziel haben, d. h. mit definierter Eigenschaft
ApplicationType
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 Projekt-Cache erstellt. Der Cache enthält alle Daten aus dem MSBuild-Projekt, die zum Beantworten von get
-Abfragen auf VCProjectEngine
-Schnittstellen erforderlich sind. 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 Bereitstellen von Visual Studio-Erweiterungen. 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 Ordners für Erweiterungen.
Zusätzliche Ressourcen
Das Microsoft Build System (MSBuild) stellt die Build-Engine und das erweiterbare XML-basierte Format für Projektdateien bereit. Sie sollten mit den grundlegenden MSBuild-Konzepten und der Funktionsweise von 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 vom 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 und Buildschritte oder neue Dateitypen hinzuzufügen. Weitere Informationen finden Sie unter Übersicht über MSBuild (Visual C++) und Arbeiten mit Projekteigenschaften.