Visual Studio C++ 專案系統擴展性和工具組整合

Visual C++ 專案系統用於 .vcxproj 檔案。 它是以 Visual Studio Common Project System (CPS) 為基礎,並提供額外的 C++ 特定擴充點,以便輕鬆整合新的工具組、組建架構和目標平台。

C++ MSBuild 目標結構

所有 .vcxproj 檔案都會匯入這些檔案:

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

這些檔案本身定義很少。 相反地,它們會根據這些屬性值匯入其他檔案:

  • $(ApplicationType)

    範例:Windows Store、Android、Linux

  • $(ApplicationTypeRevision)

    這必須是 major.minor[.build[.revision]] 格式的有效版本字串。

    範例:1.0、10.0.0.0

  • $(Platform)

    由於歷史原因,組建架構被命名為「平台」。

    範例:Win32、x86、x64、ARM

  • $(PlatformToolset)

    範例:v140、v141、v141_xp、llvm

這些屬性值會指定 $(VCTargetsPath) 根資料夾底下的資料夾名稱:

$(VCTargetsPath)\
    應用程式類型\
        $(ApplicationType)\
            $(ApplicationTypeRevision)\
                平台\
                    $(Platform)\
                        PlatformToolsets\
                            $(PlatformToolset)
    平台\
        $(Platform)\
            PlatformToolsets\
                $(PlatformToolset)

在 Windows Desktop 專案中,如果 $(ApplicationType) 是空的,就會使用 $(VCTargetsPath)\平台\ 資料夾。

新增新的平台工具組

若要新增工具組,例如現有 Win32 平台的「MyToolset」,請在 $(VCTargetsPath)\Platform\Win32\PlatformToolsets\ 下建立 MyToolset 資料夾,並在其中建立 Toolset.propsToolset.targets 檔案。

PlatformToolsets 底下的每個資料夾名稱,都會以指定平台的可用平台工具組的形式,出現在項目屬性對話方塊中,如下所示:

The Platform Toolset property in the project Property Pages dialog

在這個工具組支援的每個現有的平台資料夾中,建立類似 MyToolset 資料夾和 Toolset.propsToolset.targets 的檔案。

新增平台

若要新增平台,例如「MyPlatform」,請在 $(VCTargetsPath)\Platforms\ 底下建立 MyPlatform 資料夾,並在其中建立 Platform.default.propsPlatform.props,和 Platform.targets 檔案。 也建立 $(VCTargetsPath)\Platforms\MyPlatform\PlatformToolsets\ 資料夾,並在其中建立至少一個工具組。

每個 $(ApplicationType)$(ApplicationTypeRevision)平台資料夾下的所有資料夾名稱,都會作為專案的可用平台選項出現在 IDE 中。

The New platform choice in the New Project Platform dialog

新增應用程式類型

若要新增應用程式類型,請在 $(VCTargetsPath)\Application Type\ 下建立 MyApplicationType 資料夾,並在其中建立 Defaults.props 檔案。 應用程式類型至少需要一個修訂,因此也請建立 $(VCTargetsPath)\Application Type\MyApplicationType\1.0 資料夾,並在其中建立 Defaults.props 檔案。 您也應該建立 $(VCTargetsPath)\ApplicationType\MyApplicationType\1.0\Platforms 資料夾,並在其中建立至少一個平台。

$(ApplicationType)$(ApplicationTypeRevision) 屬性不會顯示在使用者介面中。 它們在專案範本中定義,在建立專案後無法變更。

.vcxproj 匯入樹狀結構

Microsoft C++ 屬性和目標檔案匯入的簡易樹狀結構看起來如下:

$(VCTargetsPath)\Microsoft.Cpp.Default.props
    $(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props
    $(VCTargetsPath)\ImportBefore\預設\*.props
    $(VCTargetsPath)\應用程式類型\$(ApplicationType)\Default.props
    $(VCTargetsPath)\應用程式類型\$(ApplicationType)\$(ApplicationTypeRevision)\Default.props
    $(VCTargetsPath)\應用程式類型\$(ApplicationType)\$(ApplicationTypeRevision)\平台\$(Platform)\Platform.default.props
    $(VCTargetsPath)\ImportAfter\Default\*.props

Windows Desktop 專案未定義 $(ApplicationType),因此只會匯入

$(VCTargetsPath)\Microsoft.Cpp.Default.props
    $(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props
    $(VCTargetsPath)\ImportBefore\預設\*.props
    $(VCTargetsPath)\平台\$(Platform)\Platform.default.props
    $(VCTargetsPath)\ImportAfter\Default\*.props

我們將使用 $(_PlatformFolder) 屬性來保存 $(Platform) 平台資料夾位置。 此屬性是

$(VCTargetsPath)\平台\$(Platform)

適用於 Windows 傳統型應用程式,和

$(VCTargetsPath)\應用程式類型\$(ApplicationType)\$(ApplicationTypeRevision)\平台\$(Platform)

適用於所有其他。

屬性檔案會以此順序匯入:

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

目標檔案會以此順序匯入:

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

如果您需要為工具組定義一些預設屬性,可以將檔案新增至適當的 ImportBefore 和 ImportAfter 資料夾。

編寫 Toolset.props 和 Toolset.targets 檔案

使用此工具組時,Toolset.propsToolset.targets 檔案可完全控制組建期間所發生的情況。 它們也可以控制可用的偵錯工具、某些 IDE 使用者介面,例如屬性頁對話方塊中的內容,以及專案行為的一些其他層面。

雖然工具組可以覆寫整個組建程序,但您通常只想要工具組修改或新增一些組建步驟,或使用不同的組建工具,作為現有組建程序的一部分。 若要達成此目標,工具組可以匯入的一些常見屬性和目標檔案。 根據您要工具組執行的動作,這些檔案可能有助於用作匯入或範例:

  • $(VCTargetsPath)\Microsoft.CppCommon.targets

    此檔案會定義原生組建程序的主要部分,也會匯入:

    • $(VCTargetsPath)\Microsoft.CppBuild.targets

    • $(VCTargetsPath)\Microsoft.BuildSteps.targets

    • $(MSBuildToolsPath)\Microsoft.Common.Targets

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

    設定使用 Microsoft 編譯器和目標 Windows 的工具組預設值。

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

    此檔案會決定 Windows SDK 位置,並為以 Windows 為目標的應用程式定義一些重要屬性。

整合工具組特定的目標與預設 C++ 組建程序

預設的 C++ 組建程序在 Microsoft.CppCommon.targets 中定義。 沒有呼叫任何特定組建工具的目標;它們會指定主要組建步驟、其順序和相依性。

C++ 組建有三個主要步驟,由下列目標表示:

  • BuildGenerateSources

  • BuildCompile

  • BuildLink

因為每個組建步驟都可以獨立執行,因此在單一步驟中執行的目標不能依賴以不同步驟一部分執行的目標中所定義的專案群組和屬性。 此分隔允許特定組建效能最佳化。 雖然預設不會使用它,但仍建議您接受此分隔。

在每個步驟內執行的目標是由這些屬性所控制:

  • $(BuildGenerateSourcesTargets)

  • $(BuildCompileTargets)

  • $(BeforeBuildLinkTargets)

每個步驟也有 Before 和 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)" />

如需每個步驟中包含的目標範例,請參閱 Microsoft.CppBuild.targets 檔案:

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

如果您檢視目標,例如 _ClCompile,您會看到它們本身不會直接執行任何動作,而是依賴其他目標,包括 ClCompile

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

ClCompile 和其他組建工具特定目標會定義為 Microsoft.CppBuild.targets 中的空白目標:

<Target Name="ClCompile"/>

因為 ClCompile 目標是空的,除非工具組覆寫目標,否則不會執行實際的組建動作。 工具組目標可以覆寫 ClCompile 目標,也就是說,它們可以在匯入 Microsoft.CppBuild.targets 之後包含另一個 ClCompile 定義:

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

儘管它的名稱是在 Visual Studio 實作跨平台支援之前建立的,但 ClCompile 目標不需要呼叫 CL.exe。 它也可以使用適當的 MSBuild 工作來呼叫 Clang、gcc 或其他編譯器。

ClCompile 目標不應具有 SelectClCompile 目標之外的任何相依性,這是單一檔案編譯命令在 IDE 中工作所必需的。

要用於工具組目標的 MSBuild 工作

若要叫用實際的組建工具,目標必須呼叫 MSBuild 工作。 有一項可讓您指定要執行之命令列的基本 Exec 工作。 不過,組建工具通常有許多選項、輸入。 和輸出來追蹤累加組建,因此為它們分配特殊任務更有意義。 例如,CL 工作會將 MSBuild 屬性轉譯成 CL.exe 參數、將它們寫入回應檔案,以及呼叫 CL.exe。 它也會追蹤所有輸入和輸出檔案,以供後續的累加組建使用。 有關詳細資訊,請參閱累加組建和最新檢查

Microsoft.Cpp.Common.Tasks.dll 會實作下列工作:

  • BSCMake

  • CL

  • ClangCompile (clang-gcc 參數)

  • LIB

  • LINK

  • MIDL

  • Mt

  • RC

  • XDCMake

  • CustomBuild (如 Exec,但具有輸入和輸出追蹤)

  • SetEnv

  • GetOutOfDateItems

如果您有與現有工具執行相同動作的工具,而且具有類似的命令列參數 (如 clang-cl 和 CL 所作的),則可以對它們使用相同的工作。

如果您需要為組建工具建立新工作,您可以從下列選項中選擇:

  1. 如果您很少使用此工作,或幾秒鐘不影響您的組建,您可以使用 MSBuild「內嵌」工作:

    • Xaml 工作 (自訂組建規則)

      如需 Xaml 工作宣告的其中一個範例,請參閱 $(VCTargetsPath)\BuildCustomizations\masm.xml,及其使用方式,請參閱 $(VCTargetsPath)\BuildCustomizations\masm.targets

    • 程式碼工作

  2. 如果您想要更好的工作效能或只需要更複雜的功能,請使用一般 MSBuild 工作撰寫程序。

    如果工具命令列上未列出工具的所有輸入和輸出,如CLMIDL,和 RC 案例,而且如果您想要自動輸入及輸出檔案追蹤和 .tlog 檔案建立,請從 Microsoft.Build.CPPTasks.TrackedVCToolTask 類別衍生您的工作。 目前,雖然有與基底 ToolTask 類別相關的文件,但沒有與 TrackedVCToolTask 類別詳細資料相關的範例或文件。 如果對此特別感興趣,請在開發人員社群上表達您的意見。

累加組建和最新檢查

預設 MSBuild 累加組建目標會使用 InputsOutputs 屬性。 如果您指定它們,MSBuild 只有在任何輸入的時間戳記都比所有輸出都新時,才會呼叫目標。 因為來源檔案通常會包含或匯入其他檔案,而組建工具會根據工具選項產生不同的輸出,所以很難在 MSBuild 目標中指定所有可能的輸入和輸出。

為了管理這個問題,C++ 組建會使用不同的技術來支援累加組建。 大部分的目標不會指定輸入和輸出,因此一律會在組建期間執行。 目標所呼叫的工作會將所有輸入和輸出的相關資訊寫入具有 .tlog 副檔名的 tlog 檔案中。 稍後的組建會使用 .tlog 檔案來檢查哪些已變更且需要重建,以及最新狀態。 .tlog 檔案也是 IDE 中預設組建最新檢查的唯一來源。

若要判斷所有輸入和輸出,原生工具工作會使用 MSBuild 所提供的 tracker.exe 和 FileTracker 類別。

Microsoft.Build.CPPTasks.Common.dll 定義 TrackedVCToolTask 公用抽象基底類別。 大部分原生工具工作都是衍生自這個類別。

從 Visual Studio 2017 更新 15.8 開始,您可以使用 GetOutOfDateItems Microsoft.Cpp.Common.Tasks.dll 中實作的工作,針對具有已知輸入和輸出的自訂目標產生 .tlog 檔案。 或者,您可以使用 WriteLinesToFile 工作來建立它們。 請參閱 $(VCTargetsPath)\BuildCustomizations\masm.targets 中的 _WriteMasmTlogs 目標作為範例。

.tlog 檔案

.tlog 檔案有三種類型:讀取寫入,和命令列。 累加組建和 IDE 中的最新檢查會使用讀取和寫入 .tlog 檔案。 命令列 .tlog 檔案只會用於累加組建中。

MSBuild 提供這些協助程式類別來讀取和寫入 .tlog 檔案:

FlatTrackingData 類別可用來存取讀取和寫入 .tlog 檔案,並識別比輸出還新的輸入,或輸出是否遺失。 它用於最新檢查中。

命令列 .tlog 檔案包含組建中使用的命令列相關資訊。 它們僅用於累加組建,而不是最新檢查,因此內部格式是由產生它們的 MSBuild 工作所決定。

讀取 .tlog 格式

讀取 .tlog 檔案 (*.read.*.tlog) 包含來源檔案及其相依性的相關資訊。

行開頭的插入號 (^) 表示一或多個來源。 共用相同相依性的來源會以分隔號 (|) 分隔。

相依性檔案會列在來源後面,每一個獨佔一行。 所有檔案名稱都是完整路徑。

例如,假設您的專案來源位於 F:\test\ConsoleApplication1\ConsoleApplication1。 如果您的來源檔案,Class1.cpp,包含這個,

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

CL.read.1.tlog 檔案包含來源檔案及其兩個相依性:

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

檔案名稱不需要大寫,但這對某些工具來說很方便。

寫入 .tlog 格式

寫入 .tlog (*.write.*.tlog) 檔案會連接來源和輸出。

行開頭的插入號 (^) 表示一或多個來源。 多個來源會以分隔號分隔 (|)。

從來源組建的輸出檔案應該列在來源之後,每一個獨佔一行。 所有檔案名稱都必須是完整路徑。

例如,對於具有其他來源檔案 Class1.cpp 的簡單 ConsoleApplication 專案,link.write.1.tlog 檔案可能包含:

^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

設計時間組建

在 IDE 中,.vcxproj 專案會使用一組 MSBuild 目標,從專案取得其他資訊以及重新產生輸出檔案。 其中有些目標只用於設計時間組建,但許多目標都用於一般組建和設計時間組建。

如需設計時間組建的一般資訊,請參閱設計時間組建的 CPS檔。 本文件僅部分適用於 Visual C++ 專案。

設計時間組建文件中提及的 CompileDesignTimeCompile 目標,永遠不會在 .vcxproj 專案中執行。 Visual C++ .vcxproj 專案使用不同的設計時間目標來取得 IntelliSense 資訊。

IntelliSense 資訊的設計時間目標

.vcxproj 專案中所使用的設計時間目標,在 $(VCTargetsPath)\Microsoft.Cpp.DesignTime.targets 中定義。

GetClCommandLines 目標會收集 IntelliSense 的編譯器選項:

<Target
  Name="GetClCommandLines"
  Returns="@(ClCommandLines)"
  DependsOnTargets="$(DesignTimeBuildInitTargets);$(ComputeCompileInputsTargets)">
  • DesignTimeBuildInitTargets – 僅限設計時間的目標,是設計時間組建初始化所需的目標。 除此之外,這些目標會停用一些一般組建功能來改善效能。

  • ComputeCompileInputsTargets – 一組修改編譯器選項和項目的目標。 這些目標會在設計時間和一般組建中執行。

目標會呼叫 CLCommandLine工作,以建立要用於 IntelliSense 的命令列。 同樣,儘管它的名字如此,它不僅可以處理 CL 選項,還可以處理 Clang 和 gcc 選項。 編譯器參數的類型是由 ClangMode 屬性所控制。

目前,CLCommandLine 工作所產生的命令列,一律會使用 CL 參數 (即使在 Clang 模式中),因為它們更容易被 IntelliSense 引擎剖析。

如果您要新增在編譯之前執行的目標 (無論是一般或設計時間),請確保其不會中斷設計時間組建或影響效能。 測試目標最簡單的方式,就是開啟開發人員命令提示字元並執行此命令:

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

此命令會產生詳細的組建記錄,msbuild.log,該記錄最後有目標和工作的效能摘要。

確保在僅對一般組建有意義而不對設計時間組建有意義的所有操作中使用 Condition ="'$(DesignTimeBuild)' != 'true'"

產生來源的設計時間目標

預設情況下,此功能在傳統型原生專案中處於停用狀態,且目前在快取專案中不受支援

如果 GeneratorTarget 中繼資料是為專案項目所定義,當載入專案和變更來源檔案時,就會自動執行目標。

例如,若要從 .xaml 檔案自動產生.cpp或 .h 檔案,$(VSInstallDir)\MSBuild\Microsoft\WindowsXaml\v16.0\*\Microsoft.Windows.UI.Xaml.CPP.Targets 檔案會定義這些實體:

<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 來取得來源檔案的未儲存內容,目標與工作應註冊為 pkgdef 中指定專案的 MsbuildHostObjects

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

Visual Studio IDE 中的 Visual C++ 專案擴充性

Visual C++ 專案系統是以 VS 專案系統為基礎,並使用其擴充點。 不過,專案階層實作是 Visual C++ 特有的,而不是以 CPS 為基礎,因此階層擴充性僅限於專案項目。

專案屬性頁

如需一般設計資訊,請參閱 VC++ 專案的架構多目標

簡單來說,您在 C++ 專案的專案屬性對話方塊中看到的屬性頁,是由規則檔案所定義。 規則檔案會指定要在屬性頁面上顯示的一組屬性,以及它們應該儲存在專案檔案中的方式和位置。 規則檔案是使用 Xaml 格式的 .xml 檔案。 用來序列化的類型會在 Microsoft.Build.Framework.XamlTypes 中描述。 如需在專案中使用規則檔案的詳細資訊,請參閱屬性頁 XML 規則檔案

規則檔案必須新增至 PropertyPageSchema 項目群組:

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

Context 中繼資料會限制規則能見度,此能見度也由規則類型控制,而且可以有下列其中一個值:

Project | File | PropertySheet

CPS 支援內容類型的其他值,但在 Visual C++ 專案中不會使用。

如果規則應該顯示在多個內容中,請使用分號 (;) 來分隔內容值,如下所示:

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

規則格式和主要類型

規則格式很簡單,因此本節只會描述影響規則在使用者介面中外觀的屬性。

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

PageTemplate 屬性定義規則在 屬性頁對話方塊中的顯示方式。 屬性可以有下列其中一個值:

屬性 描述
generic 所有屬性都會顯示在 [類別] 標題下的一個頁面上
此規則在 ProjectPropertySheet 內容中可見,但在 File 中不可見。

範例:$(VCTargetsPath)\1033\general.xml
tool 類別會顯示為子頁面。
規則在所有內容中都可以看見:ProjectPropertySheetFile
只有當專案具有 Rule.DataSource 中定義的 ItemType 項目時,規則才在項 [專案屬性] 中可見,除非規則名稱包含在 ProjectTools 項目群組中。

範例:$(VCTargetsPath)\1033\clang.xml
debugger 該頁面會顯示為 [偵錯] 頁面的一部分。
目前忽略的類別。
規則名稱應該符合 [偵錯啟動器 MEF] 物件的 ExportDebugger 屬性。

範例:$(VCTargetsPath)\1033\debugger_local_windows.xml
custom 自訂範本。 範本的名稱應該符合 PropertyPageUIFactoryProvider MEF物件的 ExportPropertyPageUIFactoryProvider 屬性。 請參閱 Microsoft.VisualStudio.ProjectSystem.Designers.Properties.IPropertyPageUIFactoryProvider

範例:$(VCTargetsPath)\1033\userMacros.xml

如果規則使用其中一個以屬性方格為基礎的範本,它可以針對其屬性使用這些擴充點:

擴充規則

如果您想要使用現有的規則,但只需要新增或移除 (即,隱藏) 幾個屬性,您可以建立擴充規則

覆蓋規則

也許您希望工具組使用大部分專案預設規則,但只取代其中一個或一些規則。 例如,假設您只想變更 C/C++ 規則以顯示不同的編譯器參數。 您可以提供與現有規則的名稱和顯示名稱相同的新規則,並在匯入預設 cpp 目標之後將其包含在 PropertyPageSchema 項目群組中。 專案中只會使用具有指定名稱的一個規則,最後一個包含在 PropertyPageSchema 項目群組中的規則獲勝。

專案項目

ProjectItemsSchema.xml 檔案會定義將項目視為專案項目的 ContentTypeItemType 值,並定義 FileExtension 項目以判斷新檔案要新增到哪個項目群組。

預設 ProjectItemsSchema 檔案位在 $(VCTargetsPath)\1033\ProjectItemsSchema.xml。 若要將其擴充,您必須建立具有新名稱的結構描述檔案,例如 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>

然後在目標檔案中,新增:

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

範例:$(VCTargetsPath)\BuildCustomizations\masm.xml

偵錯工具

Visual Studio 中的偵錯服務支援偵錯引擎的擴充性。 如需詳細資訊,請參閱下列範例:

若要指定偵錯工作階段的偵錯引擎和其他屬性,您必須實偵錯啟動器 MEF 元件,並新增 debugger 規則。 如需範例,請參閱 $(VCTargetsPath) \1033\debugger_local_windows.xml 檔案。

部署

.vcxproj 專案使用部署提供者的 Visual Studio 專案系統擴充性。

組建最新檢查

根據預設,組建最新檢查需要讀取 .tlog 和寫入 .tlog 檔案,才能在組建期間在 $(TlogLocation) 資料夾中建立所有組建輸入和輸出。

若要使用自訂最新檢查:

  1. Toolset.targets 檔案中新增 NoVCDefaultBuildUpToDateCheckProvider 功能,以停用預設最新檢查:

    <ItemGroup>
      <ProjectCapability Include="NoVCDefaultBuildUpToDateCheckProvider" />
    </ItemGroup>
    
  2. 實作您自己的 IBuildUpToDateCheckProvider

專案升級

預設 .vcxproj 專案升級程式

預設 .vcxproj 專案升級程式會變更 PlatformToolsetApplicationTypeRevision、MSBuild 工具組版本和 .NET Framework。 最後兩個一律會變更為 Visual Studio 版本預設值,但 PlatformToolsetApplicationTypeRevision 可由特殊的 MSBuild 屬性控制。

升級程式會使用這些準則來決定是否可以升級專案:

  1. 對於定義 ApplicationTypeApplicationTypeRevision 的專案,有一個資料夾的修訂編號高於目前的修訂編號。

  2. 屬性 _UpgradePlatformToolsetFor_<safe_toolset_name> 會針對目前的工具組定義,而且其值不等於目前的工具組。

    在這些屬性名稱中,<safe_toolset_name> 代表工具組名稱,其中包含以底線取代的所有非英數字元 (_)。

當專案可以升級時,它就會參與 方案重定目標。 如需詳細資訊,請參閱 IVsTrackProjectRetargeting2

如果您想要在專案使用特定工具組時,在方案總管裝飾項目名稱,請定義 _PlatformToolsetShortNameFor_<safe_toolset_name> 屬性。

如需 _UpgradePlatformToolsetFor_<safe_toolset_name>_PlatformToolsetShortNameFor_<safe_toolset_name> 屬性定義的範例,請參閱 Microsoft.Cpp.Default.props 檔案。 如需使用方式的範例,請參閱 $(VCTargetPath)\Microsoft.Cpp.Platform.targets 檔案。

自訂專案升級程式

若要使用自訂專案升級程式物件,請實作 MEF 元件,如下所示:

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

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

您的程式碼可以匯入並呼叫預設 .vcxproj 升級程式物件:

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

IProjectRetargetHandler 定義於 Microsoft.VisualStudio.ProjectSystem.VS.dll 中,且類似於 IVsRetargetProjectAsync

定義 VCProjectUpgraderObjectName 屬性,告知專案系統使用您的自訂升級程式物件:

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

停用專案升級

若要停用項目升級,請使用 NoUpgrade 值:

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

專案快取和擴充性

為了改善在 Visual Studio 2017 中使用大型 C++ 方案時的效能,引進了 專案快取。 它被實作為填入了專案目資料的 SQLite 資料庫,然後用於載入專案,而無需將 MSBuild 或 CPS 專案載入到記憶體中。

由於從快取載入的 .vcxproj 專案沒有 CPS 物件,無法建立匯入 UnconfiguredProjectConfiguredProject 的擴充功能的 MEF 元件。 為了支援擴充性,當 Visual Studio 偵測到專案使用 (或可能使用) MEF 擴充功能時,專案快取不會被使用。

這些專案類型一律會完整載入且記憶體中有 CPS 物件,因此會為其建立所有 MEF 擴充功能:

  • 啟始專案

  • 具有自訂專案升級程式的專案,也就是,它們會定義 VCProjectUpgraderObjectName 屬性

  • 不以 Desktop Windows 為目標的專案,也就是,它們會定義 ApplicationType 屬性

  • 共用項目專案 (.vcxitems) 和透過匯入 .vcxitems 專案來參考這些專案的任何專案。

如果未偵測到這些條件,則會建立專案快取。 快取包含來自 MSBuild 專案的所有資料,以回應 VCProjectEngine 介面上的 get 查詢。 這表示擴充功能所完成之 MSBuild 屬性和目標檔案層級的所有修改,應該只會在從快取載入的專案中運作。

傳送擴充功能

如需如何建立 VSIX 檔案的資訊,請參閱傳送 Visual Studio 擴充功能。 如需如何將檔案新增至特殊安裝位置的資訊,例如,若要在 $(VCTargetsPath)底下新增檔案,請參閱在擴充功能資料夾外安裝

其他資源

Microsoft Build System (MSBuild) 提供專案檔案的建置引擎和可延伸的 XML 格式。 您應該熟悉基本的 MSBuild 概念,以及 MSBuild for Visual C++ 的運作方式,以擴充 Visual C++ 專案系統。

Managed Extensibility Framework (MEF) 提供 CPS 和 Visual C++ 專案系統所使用的擴充功能 API。 如需 CPS 如何使用 MEF 的概觀,請參閱 MEF VSProjectSystem 概觀 中的 CPS 和 MEF

您可以自訂現有的組建系統,以新增組建步驟或新的檔案類型。 如需詳細資訊,請參閱 MSBuild (Visual C++) 概觀使用專案屬性