Rozszerzalność systemu projektów visual Studio C++ i integracja zestawu narzędzi
System projektu Visual C++ jest używany do .vcxproj plików. Jest ona oparta na programie Visual Studio Common Project System (CPS) i udostępnia dodatkowe punkty rozszerzalności specyficzne dla języka C++ umożliwiające łatwą integrację nowych zestawów narzędzi, architektur kompilacji i platform docelowych.
Struktura obiektów docelowych programu MSBuild w języku C++
Wszystkie pliki .vcxproj są importowane:
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
Te pliki definiują niewiele samodzielnie. Zamiast tego importują inne pliki na podstawie tych wartości właściwości:
$(ApplicationType)
Przykłady: Sklep Windows, Android, Linux
$(ApplicationTypeRevision)
Musi to być prawidłowy ciąg wersji formularza major.minor[.build[.revision]].
Przykłady: 1.0, 10.0.0.0
$(Platform)
Architektura kompilacji o nazwie "Platforma" ze względów historycznych.
Przykłady: Win32, x86, x64, ARM
$(PlatformToolset)
Przykłady: v140, v141, v141_xp, llvm
Te wartości właściwości określają nazwy folderów w folderze $(VCTargetsPath)
głównym:
$(VCTargetsPath)
\
Typ aplikacji\
$(ApplicationType)
\
$(ApplicationTypeRevision)
\
Platformy\
$(Platform)
\
Zestawy narzędzi platformy\
$(PlatformToolset)
Platformy\
$(Platform)
\
Zestawy narzędzi platformy\
$(PlatformToolset)
Folder $(VCTargetsPath)
\Platformy\ jest używany, gdy $(ApplicationType)
jest pusty, w przypadku projektów klasycznych systemu Windows.
Dodawanie nowego zestawu narzędzi platformy
Aby dodać nowy zestaw narzędzi, na przykład "MyToolset" dla istniejącej platformy Win32, utwórz folder MyToolset w folderze $(VCTargetsPath)
\Platforms\Win32\PlatformToolsets\, a następnie utwórz w nim pliki Toolset.props i Toolset.targets.
Każda nazwa folderu w obszarze PlatformToolsets jest wyświetlana w oknie dialogowym Właściwości projektu jako dostępny zestaw narzędzi platformy dla określonej platformy, jak pokazano poniżej:
Utwórz podobne foldery MyToolset i pliki Toolset.props i Toolset.targets w każdym istniejącym folderze platformy, który obsługuje ten zestaw narzędzi.
Dodawanie nowej platformy
Aby dodać nową platformę, na przykład "MyPlatform", utwórz folder MyPlatform w folderze $(VCTargetsPath)
\Platforms\, a następnie utwórz w nim pliki Platform.default.props, Platform.props i Platform.targets. $(VCTargetsPath)
Utwórz również folder \Platforms\MyPlatform\PlatformToolsets\ i utwórz w nim co najmniej jeden zestaw narzędzi.
Wszystkie nazwy folderów w folderze Platformy dla każdego $(ApplicationType)
i $(ApplicationTypeRevision)
są wyświetlane w środowisku IDE jako dostępne opcje platformy dla projektu.
Dodawanie nowego typu aplikacji
Aby dodać nowy typ aplikacji, utwórz folder MyApplicationType w folderze $(VCTargetsPath)
\Application Type\ i utwórz w nim plik Defaults.props. Co najmniej jedna poprawka jest wymagana dla typu aplikacji, dlatego utwórz $(VCTargetsPath)
w nim również folder \Application Type\MyApplicationType\1.0 i utwórz w nim plik Defaults.props . Należy również utworzyć $(VCTargetsPath)
folder \ApplicationType\MyApplicationType\1.0\Platforms i utworzyć w nim co najmniej jedną platformę.
$(ApplicationType)
właściwości i $(ApplicationTypeRevision)
nie są widoczne w interfejsie użytkownika. Są one definiowane w szablonach projektów i nie można ich zmienić po utworzeniu projektu.
Drzewo importu .vcxproj
Uproszczone drzewo importów dla rekwizytów i plików docelowych języka Microsoft C++ wygląda następująco:
$(VCTargetsPath)
\Microsoft.Cpp.Default.props
$(MSBuildExtensionsPath)
\$(MSBuildToolsVersion)
\Microsoft.Common.props
$(VCTargetsPath)
\ImportBefore\Default\*.Rekwizyty
$(VCTargetsPath)
\Typ\\$(ApplicationType)
aplikacji Default.props
$(VCTargetsPath)
\Typ$(ApplicationTypeRevision)
\$(ApplicationType)
\\aplikacji Default.props
$(VCTargetsPath)
\Platformy\$(Platform)
\typów$(ApplicationType)
\\$(ApplicationTypeRevision)
\aplikacji Platform.default.props
$(VCTargetsPath)
\ImportAfter\Default\*.Rekwizyty
Projekty pulpitu z systemem Windows nie definiują $(ApplicationType)
elementu , więc importują je tylko
$(VCTargetsPath)
\Microsoft.Cpp.Default.props
$(MSBuildExtensionsPath)
\$(MSBuildToolsVersion)
\Microsoft.Common.props
$(VCTargetsPath)
\ImportBefore\Default\*.Rekwizyty
$(VCTargetsPath)
\Platformy\\$(Platform)
Platform.default.props
$(VCTargetsPath)
\ImportAfter\Default\*.Rekwizyty
Użyjemy $(_PlatformFolder)
właściwości do przechowywania $(Platform)
lokalizacji folderów platformy. Ta właściwość jest
$(VCTargetsPath)
\Platformy\$(Platform)
dla aplikacji klasycznych systemu Windows i
$(VCTargetsPath)
\Platformy typów$(ApplicationTypeRevision)
\$(ApplicationType)
\\aplikacji\$(Platform)
dla wszystkiego innego.
Pliki props są importowane w tej kolejności:
$(VCTargetsPath)
\Microsoft.Cpp.props
$(_PlatformFolder)
\Platform.props
$(VCTargetsPath)
\Microsoft.Cpp.Platform.props
$(_PlatformFolder)
\ImportBefore\*.Rekwizyty
$(_PlatformFolder)
\Zestaw narzędzi PlatformToolsets.props\$(PlatformToolset)
\
$(_PlatformFolder)
\ImportAfter\*.Rekwizyty
Pliki docelowe są importowane w następującej kolejności:
$(VCTargetsPath)
\Microsoft.Cpp.targets
$(VCTargetsPath)
\Microsoft.Cpp.Current.targets
$(_PlatformFolder)
\Platform.targets
$(VCTargetsPath)
\Microsoft.Cpp.Platform.targets
$(_PlatformFolder)
\ImportBefore\*.Cele
$(_PlatformFolder)
\Zestaw narzędzi PlatformToolsets.target\$(PlatformToolset)
\
$(_PlatformFolder)
\ImportAfter\*.Cele
Jeśli musisz zdefiniować niektóre domyślne właściwości zestawu narzędzi, możesz dodać pliki do odpowiednich folderów ImportBefore i ImportAfter.
Pliki Author Toolset.props i Toolset.targets
Pliki Toolset.props i Toolset.targets mają pełną kontrolę nad tym, co się dzieje podczas kompilacji, gdy ten zestaw narzędzi jest używany. Mogą również kontrolować dostępne debugery, niektóre interfejsy użytkownika IDE, takie jak zawartość w oknie dialogowym Strony właściwości i niektóre inne aspekty zachowania projektu.
Mimo że zestaw narzędzi może zastąpić cały proces kompilacji, zwykle zestaw narzędzi ma modyfikować lub dodawać kilka kroków kompilacji lub używać różnych narzędzi kompilacji w ramach istniejącego procesu kompilacji. Aby osiągnąć ten cel, istnieje wiele typowych rekwizytów i plików docelowych, które zestaw narzędzi może zaimportować. W zależności od tego, co chcesz zrobić w zestawie narzędzi, te pliki mogą być przydatne do użycia jako import lub jako przykłady:
$(VCTargetsPath)
\Microsoft.CppCommon.targetsTen plik definiuje główne części natywnego procesu kompilacji, a także importuje:
$(VCTargetsPath)
\Microsoft.CppBuild.targets$(VCTargetsPath)
\Microsoft.BuildSteps.targets$(MSBuildToolsPath)
\Microsoft.Common.Targets
$(VCTargetsPath)
\Microsoft.Cpp.Common.propsUstawia wartości domyślne dla zestawów narzędzi korzystających z kompilatorów firmy Microsoft i docelowego systemu Windows.
$(VCTargetsPath)
\Microsoft.Cpp.WindowsSDK.propsTen plik określa lokalizację zestawu Windows SDK i definiuje niektóre ważne właściwości dla aplikacji przeznaczonych dla systemu Windows.
Integrowanie elementów docelowych specyficznych dla zestawu narzędzi z domyślnym procesem kompilacji języka C++
Domyślny proces kompilacji języka C++ jest zdefiniowany w pliku Microsoft.CppCommon.targets. Te obiekty docelowe nie wywołają żadnych konkretnych narzędzi kompilacji; określają główne kroki kompilacji, ich kolejność i zależności.
Kompilacja języka C++ ma trzy główne kroki, które są reprezentowane przez następujące cele:
BuildGenerateSources
BuildCompile
BuildLink
Ponieważ każdy krok kompilacji może być wykonywany niezależnie, obiekty docelowe uruchomione w jednym kroku nie mogą polegać na grupach elementów i właściwościach zdefiniowanych w obiektach docelowych uruchamianych w ramach innego kroku. Ten podział umożliwia pewne optymalizacje wydajności kompilacji. Mimo że nie jest on używany domyślnie, nadal zachęcamy do honorowania tej separacji.
Obiekty docelowe, które są uruchamiane wewnątrz każdego kroku, są kontrolowane przez następujące właściwości:
$(BuildGenerateSourcesTargets)
$(BuildCompileTargets)
$(BeforeBuildLinkTargets)
Każdy krok ma również właściwości Przed i Po.
<Target
Name="_BuildGenerateSourcesAction"
DependsOnTargets="$(CommonBuildOnlyTargets);$(BeforeBuildGenerateSourcesTargets);$(BuildGenerateSourcesTargets);$(AfterBuildGenerateSourcesTargets)" />
<Target
Name="\_BuildCompileAction"
DependsOnTargets="$(CommonBuildOnlyTargets);$(BeforeBuildCompileTargets);$(BuildCompileTargets);$(AfterBuildCompileTargets)" />
<Target
Name="\_BuildLinkAction"
DependsOnTargets="$(CommonBuildOnlyTargets);$(BeforeBuildLinkTargets);$(BuildLinkTargets);$(AfterBuildLinkTargets)" />
Zobacz plik Microsoft.CppBuild.targets, aby zapoznać się z przykładami obiektów docelowych uwzględnionych w każdym kroku:
<BuildCompileTargets Condition="'$(ConfigurationType)'\!='Utility'">
$(BuildCompileTargets);
_ClCompile;
_ResGen;
_ResourceCompile;
$(BuildLibTargets);
</BuildCompileTargets>
Jeśli przyjrzysz się obiektom docelowym, takim jak _ClCompile
, zobaczysz, że nie robią nic bezpośrednio samodzielnie, ale zamiast tego zależą od innych celów, w tym ClCompile
:
<Target Name="_ClCompile"
DependsOnTargets="$(BeforeClCompileTargets);$(ComputeCompileInputsTargets);MakeDirsForCl;ClCompile;$(AfterClCompileTargets)" >
</Target>
ClCompile
i inne obiekty docelowe specyficzne dla narzędzi kompilacji są definiowane jako puste obiekty docelowe w pliku Microsoft.CppBuild.targets:
<Target Name="ClCompile"/>
Ponieważ element docelowy ClCompile
jest pusty, chyba że jest zastępowany przez zestaw narzędzi, nie jest wykonywana żadna rzeczywista akcja kompilacji. Obiekty docelowe zestawu narzędzi mogą zastąpić ClCompile
element docelowy, czyli mogą zawierać inną ClCompile
definicję po zaimportowaniu elementu Microsoft.CppBuild.targets:
<Target Name="ClCompile"
Condition="'@(ClCompile)' != ''"
DependsOnTargets="SelectClCompile">
<!-- call some MSBuild tasks -->
</Target>
Pomimo nazwy, która została utworzona przed zaimplementowaniem obsługi międzyplatformowej programu Visual Studio, ClCompile
element docelowy nie musi wywoływać CL.exe. Może również wywoływać język Clang, gcc lub inne kompilatory przy użyciu odpowiednich zadań MSBuild.
Obiekt ClCompile
docelowy nie powinien mieć żadnych zależności z wyjątkiem SelectClCompile
obiektu docelowego, który jest wymagany do działania polecenia kompilacji pojedynczego pliku w środowisku IDE.
Zadania programu MSBuild do użycia w elementach docelowych zestawu narzędzi
Aby wywołać rzeczywiste narzędzie kompilacji, element docelowy musi wywołać zadanie MSBuild. Istnieje podstawowe zadanie Exec, które umożliwia określenie wiersza polecenia do uruchomienia. Jednak narzędzia kompilacji zwykle mają wiele opcji, danych wejściowych i wyjściowych do śledzenia kompilacji przyrostowych, więc warto mieć specjalne zadania dla nich. Na przykład CL
zadanie tłumaczy właściwości msBuild na przełączniki CL.exe, zapisuje je w pliku odpowiedzi i wywołuje CL.exe. Śledzi również wszystkie pliki wejściowe i wyjściowe na potrzeby kolejnych kompilacji przyrostowych. Aby uzyskać więcej informacji, zobacz Incremental builds and up-to-date checks (Kompilacje przyrostowe i aktualne testy).
Microsoft.Cpp.Common.Tasks.dll implementuje następujące zadania:
BSCMake
CL
ClangCompile
(przełączniki clang-gcc)LIB
LINK
MIDL
Mt
RC
XDCMake
CustomBuild
(na przykład Exec, ale ze śledzeniem danych wejściowych i wyjściowych)SetEnv
GetOutOfDateItems
Jeśli masz narzędzie, które wykonuje tę samą akcję co istniejące narzędzie i ma podobne przełączniki wiersza polecenia (co clang-cl i CL do), możesz użyć tego samego zadania dla obu z nich.
Jeśli musisz utworzyć nowe zadanie dla narzędzia kompilacji, możesz wybrać jedną z następujących opcji:
Jeśli używasz tego zadania rzadko lub jeśli kilka sekund nie ma znaczenia dla kompilacji, możesz użyć zadań msBuild "wbudowanych":
Zadanie Xaml (niestandardowa reguła kompilacji)
Aby zapoznać się z jednym przykładem deklaracji zadania Xaml, zobacz
$(VCTargetsPath)
\BuildCustomizations\masm.xml i aby uzyskać informacje o jego użyciu, zobacz$(VCTargetsPath)
\BuildCustomizations\masm.targets.
Jeśli chcesz uzyskać lepszą wydajność zadań lub po prostu potrzebujesz bardziej złożonych funkcji, użyj zwykłego procesu pisania zadań MSBuild.
Jeśli nie wszystkie dane wejściowe i wyjściowe narzędzia są wyświetlane w wierszu polecenia narzędzia, tak jak w
CL
wierszach poleceń ,MIDL
iRC
przypadkach, a jeśli chcesz automatyczne śledzenie plików wejściowych i wyjściowych oraz tworzenie pliku tlog, należy utworzyć zadanie zMicrosoft.Build.CPPTasks.TrackedVCToolTask
klasy . Obecnie w dokumentacji podstawowej klasy ToolTask nie ma przykładów ani dokumentacji dotyczącej szczegółówTrackedVCToolTask
klasy. Jeśli jest to szczególnie interesujące, dodaj swój głos do żądania w społeczności deweloperów.
Kompilacje przyrostowe i aktualne kontrole
Domyślne obiekty docelowe kompilacji przyrostowej MSBuild używają Inputs
atrybutów i Outputs
. Jeśli je określisz, program MSBuild wywołuje element docelowy tylko wtedy, gdy którykolwiek z danych wejściowych ma nowszy znacznik czasu niż wszystkie dane wyjściowe. Ponieważ pliki źródłowe często zawierają lub importują inne pliki, a narzędzia kompilacji generują różne dane wyjściowe w zależności od opcji narzędzia, trudno jest określić wszystkie możliwe dane wejściowe i wyjściowe w celach programu MSBuild.
Aby zarządzać tym problemem, kompilacja języka C++ używa innej techniki do obsługi kompilacji przyrostowych. Większość obiektów docelowych nie określa danych wejściowych i wyjściowych, a w rezultacie zawsze uruchamiane podczas kompilacji. Zadania wywoływane przez obiekty docelowe zapisują informacje o wszystkich danych wejściowych i wyjściowych w plikach tlog , które mają rozszerzenie tlog. Pliki tlog są używane przez późniejsze kompilacje, aby sprawdzić, co się zmieniło i które należy ponownie skompilować oraz co jest aktualne. Pliki .tlog są również jedynym źródłem domyślnej kompilacji aktualnej ewidencjonowania w środowisku IDE.
Aby określić wszystkie dane wejściowe i wyjściowe, zadania narzędzi natywnych używają tracker.exe i klasy FileTracker dostarczonej przez program MSBuild.
Microsoft.Build.CPPTasks.Common.dll definiuje publiczną abstrakcyjną klasę TrackedVCToolTask
bazową. Większość zadań natywnych narzędzi pochodzi z tej klasy.
Począwszy od programu Visual Studio 2017 update 15.8, można użyć GetOutOfDateItems
zadania zaimplementowanego w Microsoft.Cpp.Common.Tasks.dll w celu utworzenia plików tlog dla obiektów docelowych niestandardowych ze znanymi danymi wejściowymi i wyjściowymi.
Alternatywnie można je utworzyć przy użyciu WriteLinesToFile
zadania . Zobacz element docelowy w $(VCTargetsPath)
\pliku _WriteMasmTlogs
BuildCustomizations\masm.targets jako przykład.
Pliki .tlog
Istnieją trzy typy plików tlog: odczyt, zapis i wiersz polecenia. Pliki tlog odczytu i zapisu są używane przez kompilacje przyrostowe i aktualne sprawdzanie w środowisku IDE. Pliki tlog wiersza polecenia są używane tylko w kompilacjach przyrostowych.
Program MSBuild udostępnia te klasy pomocnicze do odczytywania i zapisywania plików tlog:
Klasa FlatTrackingData może służyć do uzyskiwania dostępu zarówno do odczytu, jak i zapisu plików tlog oraz identyfikowania danych wejściowych, które są nowsze niż dane wyjściowe, lub jeśli brakuje danych wyjściowych. Jest on używany w aktualnym czeku.
Pliki .tlog wiersza polecenia zawierają informacje o wierszach polecenia używanych w kompilacji. Są one używane tylko do kompilacji przyrostowych, a nie aktualnych testów, więc format wewnętrzny jest określany przez zadanie MSBuild, które je generuje.
Odczytywanie formatu tlog
Odczytywanie plików tlog (*.read.*.tlog) zawiera informacje o plikach źródłowych i ich zależnościach.
Daszek (^) na początku wiersza wskazuje co najmniej jedno źródło. Źródła, które współużytkują te same zależności, są oddzielone pionowym paskiem (|).
Pliki zależności są wyświetlane po źródłach, z których każda znajduje się w osobnym wierszu. Wszystkie nazwy plików to pełne ścieżki.
Załóżmy na przykład, że źródła projektu znajdują się w folderze F:\test\ConsoleApplication1\ConsoleApplication1. Jeśli plik źródłowy, Class1.cpp, zawiera następujące elementy:
#include "stdafx.h" //precompiled header
#include "Class1.h"
następnie plik CL.read.1.tlog zawiera plik źródłowy, a następnie jego dwie zależności:
^F:\TEST\CONSOLEAPPLICATION1\CONSOLEAPPLICATION1\CLASS1.CPP
F:\TEST\CONSOLEAPPLICATION1\CONSOLEAPPLICATION1\DEBUG\CONSOLEAPPLICATION1.PCH
F:\TEST\CONSOLEAPPLICATION1\CONSOLEAPPLICATION1\CLASS1.H
Nie jest to wymagane do pisania nazw plików w wielkim przypadku, ale jest to wygoda dla niektórych narzędzi.
Zapis formatu tlog
Zapisuj pliki .tlog (*.write.*.tlog) łączące źródła i dane wyjściowe.
Daszek (^) na początku wiersza wskazuje co najmniej jedno źródło. Wiele źródeł jest rozdzielonych pionowym paskiem (|).
Pliki wyjściowe skompilowane ze źródeł powinny być wyświetlane po źródłach, z których każda znajduje się we własnym wierszu. Wszystkie nazwy plików muszą być pełne ścieżki.
Na przykład w przypadku prostego projektu ConsoleApplication z dodatkowym plikiem źródłowym Class1.cpp plik link.write.1.tlog może zawierać następujące elementy:
^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
Kompilacja w czasie projektowania
W środowisku IDE projekty .vcxproj używają zestawu obiektów docelowych MSBuild do uzyskiwania dodatkowych informacji z projektu i ponownego generowania plików wyjściowych. Niektóre z tych celów są używane tylko w kompilacjach w czasie projektowania, ale wiele z nich jest używanych zarówno w zwykłych kompilacjach, jak i kompilacjach w czasie projektowania.
Aby uzyskać ogólne informacje na temat kompilacji w czasie projektowania, zobacz dokumentację CPS dotyczącą kompilacji w czasie projektowania. Ta dokumentacja ma zastosowanie tylko częściowo do projektów Visual C++.
Obiekty CompileDesignTime
docelowe i Compile
wymienione w dokumentacji kompilacji w czasie projektowania nigdy nie są uruchamiane dla projektów .vcxproj. Projekty visual C++ .vcxproj używają różnych celów czasu projektowania, aby uzyskać informacje o funkcji IntelliSense.
Cele czasu projektowania dla informacji funkcji IntelliSense
Cele czasu projektowania używane w projektach .vcxproj są zdefiniowane w $(VCTargetsPath)
\pliku Microsoft.Cpp.DesignTime.targets.
Obiekt GetClCommandLines
docelowy zbiera opcje kompilatora dla funkcji IntelliSense:
<Target
Name="GetClCommandLines"
Returns="@(ClCommandLines)"
DependsOnTargets="$(DesignTimeBuildInitTargets);$(ComputeCompileInputsTargets)">
DesignTimeBuildInitTargets
— cele tylko w czasie projektowania, wymagane do inicjowania kompilacji w czasie projektowania. Między innymi te cele wyłączają niektóre z regularnych funkcji kompilacji, aby zwiększyć wydajność.ComputeCompileInputsTargets
— zestaw obiektów docelowych, który modyfikuje opcje i elementy kompilatora. Te obiekty docelowe są uruchamiane zarówno w czasie projektowania, jak i w regularnych kompilacjach.
Element docelowy CLCommandLine
wywołuje zadanie, aby utworzyć wiersz polecenia do użycia dla funkcji IntelliSense. Ponownie, pomimo nazwy, może obsługiwać nie tylko opcje CL, ale także Clang i gcc opcje. Typ przełączników kompilatora jest kontrolowany ClangMode
przez właściwość .
Obecnie wiersz polecenia generowany przez CLCommandLine
zadanie zawsze używa przełączników CL (nawet w trybie Clang), ponieważ są one łatwiejsze dla aparatu IntelliSense do analizowania.
Jeśli dodasz element docelowy uruchamiany przed kompilacją, niezależnie od tego, czy jest to regularne, czy projektowe, upewnij się, że nie przerywa kompilacji czasu projektowania ani nie wpływa na wydajność. Najprostszym sposobem testowania docelowego jest otwarcie wiersza polecenia dla deweloperów i uruchomienie tego polecenia:
msbuild /p:SolutionDir=*solution-directory-with-trailing-backslash*;Configuration=Debug;Platform=Win32;BuildingInsideVisualStudio=true;DesignTimebuild=true /t:\_PerfIntellisenseInfo /v:d /fl /fileloggerparameters:PerformanceSummary \*.vcxproj
To polecenie tworzy szczegółowy dziennik kompilacji, msbuild.log, który zawiera podsumowanie wydajności dla celów i zadań na końcu.
Pamiętaj, aby używać Condition ="'$(DesignTimeBuild)' != 'true'"
we wszystkich operacjach, które mają sens tylko w przypadku zwykłych kompilacji, a nie kompilacji w czasie projektowania.
Cele czasu projektowania, które generują źródła
Ta funkcja jest domyślnie wyłączona dla projektów natywnych dla komputerów stacjonarnych i nie jest obecnie obsługiwana w projektach buforowanych.
Jeśli GeneratorTarget
metadane są zdefiniowane dla elementu projektu, element docelowy jest uruchamiany automatycznie zarówno po załadowaniu projektu, jak i po zmianie pliku źródłowego.
Na przykład aby automatycznie generować pliki .cpp lub h z plików xaml, $(VSInstallDir)
\pliki MSBuild\Microsoft\WindowsXaml\v16.0\*\Microsoft.Windows.UI.Xaml.CPP.Targets definiują następujące jednostki:
<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>
Task.HostObject
Aby uzyskać niezapisaną zawartość plików źródłowych, obiekty docelowe i zadanie powinny być zarejestrowane jako msbuildHostObjects dla danych projektów w pliku pkgdef:
\[$RootKey$\\Projects\\{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\\MSBuildHostObjects\]
\[$RootKey$\\Projects\\{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\\MSBuildHostObjects\\DesignTimeMarkupCompilationCT;CompileXaml\]
@="{83046B3F-8984-444B-A5D2-8029DEE2DB70}"
Rozszerzalność projektu Visual C++ w środowisku IDE programu Visual Studio
System projektu Visual C++ jest oparty na systemie programu VS Project i używa jego punktów rozszerzalności. Jednak implementacja hierarchii projektu jest specyficzna dla języka Visual C++ i nie jest oparta na cpS, więc rozszerzalność hierarchii jest ograniczona do elementów projektu.
Strony właściwości projektu
Ogólne informacje o projekcie można znaleźć w temacie Framework Multi-Targeting for VC++ Projects (Wielowersyjność struktury dla projektów VC++).
Mówiąc prosto, strony właściwości widoczne w oknie dialogowym Właściwości projektu dla projektu języka C++ są definiowane przez pliki reguł . Plik reguły określa zestaw właściwości do wyświetlenia na stronie właściwości oraz sposób i miejsce ich zapisania w pliku projektu. Pliki reguł to pliki .xml, które używają formatu Xaml. Typy używane do serializacji są opisane w artykule Microsoft.Build.Framework.XamlTypes. Aby uzyskać więcej informacji na temat używania plików reguł w projektach, zobacz Pliki reguł XML strony właściwości.
Pliki reguł muszą zostać dodane do PropertyPageSchema
grupy elementów:
<ItemGroup>
<PropertyPageSchema Include="$(VCTargetsPath)$(LangID)\general.xml;"/>
<PropertyPageSchema Include="$(VCTargetsPath)$(LangID)\general_file.xml">
<Context>File</Context>
</PropertyPageSchema>
</ItemGroup>
Context
Widoczność reguły limitów metadanych, która jest również kontrolowana przez typ reguły i może mieć jedną z następujących wartości:
Project
| File
| PropertySheet
Usługa CPS obsługuje inne wartości dla typu kontekstu, ale nie są używane w projektach Visual C++.
Jeśli reguła powinna być widoczna w więcej niż jednym kontekście, użyj średników (;), aby oddzielić wartości kontekstu, jak pokazano poniżej:
<PropertyPageSchema Include="$(MyFolder)\MyRule.xml">
<Context>Project;PropertySheet</Context>
</PropertyPageSchema>
Format reguły i typy główne
Format reguły jest prosty, dlatego w tej sekcji opisano tylko atrybuty wpływające na wygląd reguły w interfejsie użytkownika.
<Rule
Name="ConfigurationGeneral"
DisplayName="General"
PageTemplate="generic"
Description="General"
xmlns="http://schemas.microsoft.com/build/2009/properties">
Atrybut PageTemplate
określa sposób wyświetlania reguły w oknie dialogowym Strony właściwości. Atrybut może mieć jedną z następujących wartości:
Atrybut | opis |
---|---|
generic |
Wszystkie właściwości są wyświetlane na jednej stronie w obszarze Nagłówki kategorii Reguła może być widoczna dla Project kontekstów i PropertySheet , ale nie File .Przykład: $(VCTargetsPath) \1033\general.xml |
tool |
Kategorie są wyświetlane jako podstrony. Reguła może być widoczna we wszystkich kontekstach: Project , PropertySheet i File .Reguła jest widoczna we właściwościach projektu tylko wtedy, gdy projekt zawiera elementy ze ItemType zdefiniowanymi w elemencie Rule.DataSource , chyba że nazwa reguły jest uwzględniona w ProjectTools grupie elementów.Przykład: $(VCTargetsPath) \1033\clang.xml |
debugger |
Strona jest wyświetlana jako część strony Debugowanie. Kategorie są obecnie ignorowane. Nazwa reguły powinna być zgodna z atrybutem obiektu MEF uruchamiania ExportDebugger debugowania.Przykład: $(VCTargetsPath) \1033\debugger_local_windows.xml |
custom | Szablon niestandardowy. Nazwa szablonu powinna być zgodna z ExportPropertyPageUIFactoryProvider atrybutem PropertyPageUIFactoryProvider obiektu MEF. Zobacz Microsoft.VisualStudio.ProjectSystem.Designers.Properties.IPropertyPageUIFactoryProvider.Przykład: $(VCTargetsPath) \1033\userMacros.xml |
Jeśli reguła używa jednego z szablonów opartych na siatce właściwości, może użyć tych punktów rozszerzalności dla jego właściwości:
Rozszerzanie reguły
Jeśli chcesz użyć istniejącej reguły, ale musisz dodać lub usunąć (czyli ukryć) tylko kilka właściwości, możesz utworzyć regułę rozszerzenia.
Zastępowanie reguły
Być może chcesz, aby zestaw narzędzi używał większości reguł domyślnych projektu, ale zastąpić tylko jedną lub kilka z nich. Załóżmy na przykład, że chcesz zmienić regułę języka C/C++, aby wyświetlić różne przełączniki kompilatora. Możesz podać nową regułę o tej samej nazwie i nazwie wyświetlanej co istniejąca reguła i dołączyć ją do PropertyPageSchema
grupy elementów po zaimportowaniu domyślnych obiektów docelowych cpp. W projekcie jest używana tylko jedna reguła o podanej nazwie, a ostatnia zawarta w PropertyPageSchema
grupie elementów wygrywa.
Towary w ramach projektu
Plik ProjectItemsSchema.xml definiuje ContentType
wartości i ItemType
dla elementów, które są traktowane jako elementy projektu, i definiuje FileExtension
elementy w celu określenia, do której grupy elementów jest dodawany nowy plik.
Domyślny plik ProjectItemsSchema znajduje się w $(VCTargetsPath)
\ProjectItemsSchema.xml 1033.\ Aby go rozszerzyć, należy utworzyć plik schematu o nowej nazwie, na przykład 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>
Następnie w pliku targets dodaj:
<ItemGroup>
<PropertyPageSchema Include="MyProjectItemsSchema.xml"/>
</ItemGroup>
Przykład: $(VCTargetsPath)
\BuildCustomizations\masm.xml
Debugery
Usługa Debugowanie w programie Visual Studio obsługuje rozszerzalność aparatu debugowania. Aby uzyskać więcej informacji, zobacz następujące przykłady:
Aby określić aparaty debugowania i inne właściwości sesji debugowania, należy zaimplementować składnik MEF debugowania i dodać regułę debugger
. Na przykład zobacz $(VCTargetsPath)
plik \1033\debugger_local_windows.xml.
Wdróż
.vcxproj projekty używają rozszerzalności programu Visual Studio Project System dla dostawców wdrażania.
Tworzenie aktualnego sprawdzania
Domyślnie funkcja sprawdzania kompilacji wymaga utworzenia plików tlog i zapisu tlog w $(TlogLocation)
folderze podczas kompilacji dla wszystkich danych wejściowych i wyjściowych kompilacji.
Aby użyć niestandardowego sprawdzania aktualności:
Wyłącz domyślne sprawdzanie aktualne, dodając
NoVCDefaultBuildUpToDateCheckProvider
funkcję w pliku Toolset.targets :<ItemGroup> <ProjectCapability Include="NoVCDefaultBuildUpToDateCheckProvider" /> </ItemGroup>
Zaimplementuj własny IBuildUpToDateCheckProvider.
Uaktualnianie projektu
Domyślny program uaktualniania projektu .vcxproj
Domyślny .vcxproj uaktualniania projektu zmienia PlatformToolset
ApplicationTypeRevision
wersję zestawu narzędzi MSBuild i .NET Framework. Ostatnie dwa są zawsze zmieniane na domyślne wersje programu Visual Studio, ale PlatformToolset
mogą ApplicationTypeRevision
być kontrolowane przez specjalne właściwości programu MSBuild.
Uaktualnianie używa tych kryteriów, aby zdecydować, czy projekt można uaktualnić, czy nie:
W przypadku projektów definiujących
ApplicationType
wartości iApplicationTypeRevision
istnieje folder o wyższym numerze poprawki niż bieżący.Właściwość
_UpgradePlatformToolsetFor_<safe_toolset_name>
jest zdefiniowana dla bieżącego zestawu narzędzi, a jego wartość nie jest równa bieżącemu zestawowi narzędzi.W tych nazwach <właściwości safe_toolset_name> reprezentuje nazwę zestawu narzędzi ze wszystkimi znakami innych niż alfanumeryczne zastąpione znakiem podkreślenia (_).
Po uaktualnieniu projektu uczestniczy on w retargetingu rozwiązań. Aby uzyskać więcej informacji, zobacz IVsTrackProjectRetargeting2.
Jeśli chcesz ozdobić nazwy projektów w Eksplorator rozwiązań, gdy projekty używają określonego zestawu narzędzi, zdefiniuj _PlatformToolsetShortNameFor_<safe_toolset_name>
właściwość.
_UpgradePlatformToolsetFor_<safe_toolset_name>
Przykłady definicji właściwości i _PlatformToolsetShortNameFor_<safe_toolset_name>
można znaleźć w pliku Microsoft.Cpp.Default.props. Przykłady użycia można znaleźć w $(VCTargetPath)
\pliku Microsoft.Cpp.Platform.targets.
Niestandardowy moduł uaktualniania projektu
Aby użyć niestandardowego obiektu uaktualniania projektu, zaimplementuj składnik MEF, jak pokazano poniżej:
/// </summary>
[Export("MyProjectUpgrader", typeof(IProjectRetargetHandler))]
[Export(typeof(IProjectRetargetHandler))]
[ExportMetadata("Name", "MyProjectUpgrader")]
[OrderPrecedence(20)]
[PartMetadata(ProjectCapabilities.Requires, ProjectCapabilities.VisualC)]
internal class MyProjectUpgrader: IProjectRetargetHandler
{
// ...
}
Kod może importować i wywoływać domyślny obiekt .vcxproj upgrader:
// ...
[Import("VCDefaultProjectUpgrader")]
// ...
IProjectRetargetHandler Lazy<IProjectRetargetHandler>
VCDefaultProjectUpgrader { get; set; }
// ...
IProjectRetargetHandler
jest zdefiniowany w Microsoft.VisualStudio.ProjectSystem.VS.dll i jest podobny do IVsRetargetProjectAsync
.
Zdefiniuj VCProjectUpgraderObjectName
właściwość , aby poinformować system projektu o użyciu niestandardowego obiektu uaktualniania:
<PropertyGroup>
<VCProjectUpgraderObjectName>MyProjectUpgrader</VCProjectUpgraderObjectName>
</PropertyGroup>
Wyłączanie uaktualniania projektu
Aby wyłączyć uaktualnienia projektu, użyj NoUpgrade
wartości:
<PropertyGroup>
<VCProjectUpgraderObjectName>NoUpgrade</VCProjectUpgraderObjectName>
</PropertyGroup>
Pamięć podręczna i rozszerzalność projektu
Aby zwiększyć wydajność podczas pracy z dużymi rozwiązaniami języka C++ w programie Visual Studio 2017, wprowadzono pamięć podręczną projektu. Jest implementowana jako baza danych SQLite wypełniona danymi projektu, a następnie używana do ładowania projektów bez ładowania projektów MSBuild lub CPS do pamięci.
Ponieważ nie ma żadnych obiektów CPS dla projektów .vcxproj załadowanych z pamięci podręcznej, składniki MEF rozszerzenia, które importują UnconfiguredProject
lub ConfiguredProject
nie można ich utworzyć. Aby zapewnić rozszerzalność, pamięć podręczna projektu nie jest używana, gdy program Visual Studio wykryje, czy projekt używa (lub prawdopodobnie używa) rozszerzeń MEF.
Te typy projektów są zawsze w pełni ładowane i mają obiekty CPS w pamięci, więc wszystkie rozszerzenia MEF są tworzone dla nich:
Projekty startowe
Projekty z niestandardowym uaktualnieniem
VCProjectUpgraderObjectName
projektu, czyli definiują właściwośćProjekty, które nie są przeznaczone dla systemu Windows pulpitu, czyli definiują
ApplicationType
właściwośćProjekty elementów udostępnionych (vcxitems) i wszystkie projekty odwołujące się do nich przez zaimportowanie projektów vcxitems.
Jeśli żaden z tych warunków nie zostanie wykryty, zostanie utworzona pamięć podręczna projektu. Pamięć podręczna zawiera wszystkie dane z projektu MSBuild wymagane do odpowiadania na get
zapytania dotyczące VCProjectEngine
interfejsów. Oznacza to, że wszystkie modyfikacje na poziomie plików msBuild i docelowych wykonywane przez rozszerzenie powinny działać tylko w projektach załadowanych z pamięci podręcznej.
Wysyłanie rozszerzenia
Aby uzyskać informacje na temat tworzenia plików VSIX, zobacz Wysyłanie rozszerzeń programu Visual Studio. Aby uzyskać informacje na temat dodawania plików do specjalnych lokalizacji instalacji, na przykład w celu dodania plików w obszarze $(VCTargetsPath)
, zobacz Instalowanie poza folderem rozszerzeń.
Dodatkowe zasoby
System Microsoft Build System (MSBuild) udostępnia aparat kompilacji i rozszerzalny format XML dla plików projektu. Należy zapoznać się z podstawowymi pojęciami programu MSBuild i sposobem działania programu MSBuild dla języka Visual C++ w celu rozszerzenia systemu projektu Visual C++.
Platforma Managed Extensibility Framework (MEF) udostępnia interfejsy API rozszerzeń, które są używane przez cpS i system projektu Visual C++. Aby zapoznać się z omówieniem sposobu, w jaki meF jest używany przez cpS, zobacz CPS i MEF w temacie VSProjectSystem overview of MEF (Omówienie interfejsu MEF w programie VSProjectSystem).
Możesz dostosować istniejący system kompilacji, aby dodać kroki kompilacji lub nowe typy plików. Aby uzyskać więcej informacji, zobacz MSBuild (Visual C++) Overview and Working with project properties (Omówienie programu MSBuild (Visual C++) i Praca z właściwościami projektu.