Интеграция с набором инструментов и расширяемостью системы проекта 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, Android, Linux

  • $(ApplicationTypeRevision)

    Это должна быть допустимая строка версии формы major.minor[.build[.version].

    Примеры: 1.0, 10.0.0.0

  • $(Platform)

    Архитектура сборки с именем Platform по историческим причинам.

    Примеры: Win32, x86, x64, ARM

  • $(PlatformToolset)

    Примеры: v140, v141, v141_xp, llvm

Эти значения свойств указывают имена папок в корневой папке $(VCTargetsPath) :

$(VCTargetsPath)\
    Тип приложения\
        $(ApplicationType)\
            $(ApplicationTypeRevision)\
                Платформы\
                    $(Platform)\
                        PlatformToolsets\
                            $(PlatformToolset)
    Платформы\
        $(Platform)\
            PlatformToolsets\
                $(PlatformToolset)

Папка $(VCTargetsPath)\Platform\ используется при $(ApplicationType) пустом использовании для проектов Windows Desktop.

Добавление нового набора инструментов платформы

Чтобы добавить новый набор инструментов, например MyToolset для существующей платформы Win32, создайте папку MyToolset в папке \Platform\Win32\PlatformToolsets\, а также создайте в нем файлы Toolset.props и Toolset.targets.$(VCTargetsPath)

Каждое имя папки в platformToolsets отображается в диалоговом окне "Свойства проекта" в качестве доступного набора инструментов платформы для указанной платформы, как показано ниже:

The Platform Toolset property in the project Property Pages dialog

Создайте аналогичные папки MyToolset и файлы Toolset.props и Toolset.targets в каждой существующей папке платформы, поддерживающей этот набор инструментов.

Добавление новой платформы

Чтобы добавить новую платформу, например MyPlatform, создайте папку MyPlatform в $(VCTargetsPath)папке \Platform\, и создайте в нем файлы Platform.default.props, Platform.props и Platform.targets. Кроме того, создайте папку \Platform\MyPlatform\PlatformToolsets\ и создайте в ней $(VCTargetsPath)хотя бы один набор инструментов.

Все имена папок в папке "Платформы " для каждого $(ApplicationType) и $(ApplicationTypeRevision) отображаются в интегрированной среде разработки в качестве доступных вариантов платформы для проекта.

The New platform choice in the New Project Platform dialog

Добавление нового типа приложения

Чтобы добавить новый тип приложения, создайте папку MyApplicationType в разделе$(VCTargetsPath) \Application Type\ и создайте в нем файл Defaults.props. Для типа приложения требуется по крайней мере одна редакция, поэтому создайте папку \Application Type\MyApplicationType\1.0 и создайте $(VCTargetsPath)в ней файл Defaults.props. Необходимо также создать папку $(VCTargetsPath)\ApplicationType\MyApplicationType\1.0\Platform и создать по крайней мере одну платформу в ней.

$(ApplicationType) и $(ApplicationTypeRevision) свойства не отображаются в пользовательском интерфейсе. Они определены в шаблонах проектов и не могут быть изменены после создания проекта.

Дерево импорта .vcxproj

Упрощенное дерево импорта для props и целевых файлов Microsoft C++ выглядит следующим образом:

$(VCTargetsPath)\Microsoft.Cpp.Default.props
    $(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props
    $(VCTargetsPath)\ImportBefore\Default\*.Реквизит
    $(VCTargetsPath)\Тип\\$(ApplicationType)приложения Default.props
    $(VCTargetsPath)\Тип$(ApplicationTypeRevision)\$(ApplicationType)\\приложения Default.props
    $(VCTargetsPath)\Платформы типов$(ApplicationTypeRevision)\$(ApplicationType)\\приложений\$(Platform)\Platform.default.props
    $(VCTargetsPath)\ImportAfter\Default\*.Реквизит

Проекты windows Desktop не определяются $(ApplicationType), поэтому импортируются только

$(VCTargetsPath)\Microsoft.Cpp.Default.props
    $(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props
    $(VCTargetsPath)\ImportBefore\Default\*.Реквизит
    $(VCTargetsPath)\Платформы\\$(Platform)Platform.default.props
    $(VCTargetsPath)\ImportAfter\Default\*.Реквизит

Мы будем использовать $(_PlatformFolder) свойство для хранения расположений $(Platform) папок платформы. Это свойство

$(VCTargetsPath)\Платформы\$(Platform)

для классических приложений Windows и

$(VCTargetsPath)\Платформы типов$(ApplicationTypeRevision)\$(ApplicationType)\\приложений\$(Platform)

для всего остального.

Файлы реквизитов импортируются в этом порядке:

$(VCTargetsPath)\Microsoft.Cpp.props
    $(_PlatformFolder)\Platform.props
        $(VCTargetsPath)\Microsoft.Cpp.Platform.props
            $(_PlatformFolder)\ImportBefore\*.Реквизит
            $(_PlatformFolder)\PlatformToolsets\\$(PlatformToolset)Toolset.props
            $(_PlatformFolder)\ImportAfter\*.Реквизит

Файлы целевых объектов импортируются в этом порядке:

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

Если необходимо определить некоторые свойства по умолчанию для набора инструментов, можно добавить файлы в соответствующие папки ImportBefore и ImportAfter.

Создание файлов Toolset.props и Toolset.targets

Файлы Toolset.props и Toolset.targets имеют полный контроль над тем, что происходит во время сборки при использовании этого набора инструментов. Они также могут контролировать доступные отладчики, некоторые из пользовательского интерфейса интегрированной среды разработки, такие как содержимое диалогового окна "Страницы свойств" и некоторые другие аспекты поведения проекта.

Хотя набор инструментов может переопределить весь процесс сборки, обычно вам нужно, чтобы набор инструментов изменял или добавлял некоторые шаги сборки или использовал различные средства сборки в рамках существующего процесса сборки. Для достижения этой цели существует ряд общих реквизитов и целевых файлов, которые могут импортировать набор инструментов. В зависимости от того, что вы хотите сделать набор инструментов, эти файлы могут быть полезны для использования в качестве импорта или в качестве примеров:

  • $(VCTargetsPath)\Microsoft.CppCommon.targets

    Этот файл определяет основные части собственного процесса сборки, а также импортирует:

    • $(VCTargetsPath)\Microsoft.CppBuild.targets

    • $(VCTargetsPath)\Microsoft.BuildSteps.targets

    • $(MSBuildToolsPath)\Microsoft.Common.Targets

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

    Задает значения по умолчанию для наборов инструментов, использующих компиляторы Майкрософт и целевые windows.

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

    Этот файл определяет расположение пакета SDK для Windows и определяет некоторые важные свойства для приложений, предназначенных для Windows.

Интеграция целевых объектов набора инструментов с процессом сборки C++ по умолчанию

Процесс сборки C++ по умолчанию определен в Microsoft.CppCommon.targets. Целевые объекты не вызывают никаких конкретных средств сборки; они указывают основные этапы сборки, их порядок и зависимости.

Сборка C++ состоит из трех основных шагов, которые представлены следующими целевыми объектами:

  • BuildGenerateSources

  • BuildCompile

  • BuildLink

Так как каждый шаг сборки может выполняться независимо, целевые объекты, выполняемые на одном шаге, не могут полагаться на группы элементов и свойства, определенные в целевых объектах, которые выполняются в рамках другого шага. Это разделение позволяет оптимизировать производительность сборки. Хотя он не используется по умолчанию, вы по-прежнему рекомендуется учитывать это разделение.

Целевые объекты, выполняемые внутри каждого шага, управляются этими свойствами:

  • $(BuildGenerateSourcesTargets)

  • $(BuildCompileTargets)

  • $(BeforeBuildLinkTargets)

Каждый шаг также имеет свойства "До" и "После".

<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 объект, то есть содержать другое ClCompile определение после импорта Microsoft.CppBuild.targets:

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

Несмотря на его имя, которое было создано до реализации кроссплатформенной поддержки Visual Studio, ClCompile целевой объект не должен вызывать CL.exe. Он также может вызывать Clang, gcc или другие компиляторы с помощью соответствующих задач MSBuild.

Целевой ClCompile объект не должен иметь зависимостей, кроме целевого SelectClCompile объекта, который требуется для выполнения команды компиляции одного файла для работы в интегрированной среде разработки.

Задачи 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 inline:

    • Задача Xaml (настраиваемое правило сборки)

      Один из примеров объявления задачи Xaml см. в статье $(VCTargetsPath)\BuildCustomizations\masm.xml и сведения об его использовании см. в статье $(VCTargetsPath)\BuildCustomizations\masm.targets.

    • Задача кода

  2. Если вы хотите повысить производительность задач или просто требуется более сложная функциональность, используйте обычный процесс записи задач MSBuild.

    Если не все входные и выходные данные средства перечислены в командной строке средства, как и в CLMIDLслучаях, и RC в случаях, а также если требуется автоматическое отслеживание входных и выходных файлов и создание TLOG-файла, наследуйте задачу из Microsoft.Build.CPPTasks.TrackedVCToolTask класса. В настоящее время в документации по базовому классу ToolTask нет примеров или документации для подробных сведений о TrackedVCToolTask классе. Если это будет особенно интересно, добавьте свой голос в запрос по Сообщество разработчиков.

Добавочные сборки и актуальные проверка

Целевые объекты добавочной сборки MSBuild по умолчанию используют Inputs и Outputs атрибуты. Если указать их, MSBuild вызывает целевой объект только в том случае, если любой из входных данных имеет более новую метку времени, чем все выходные данные. Так как исходные файлы часто включают или импортируют другие файлы, а средства сборки создают различные выходные данные в зависимости от параметров средства, трудно указать все возможные входные и выходные данные в целевых объектах MSBuild.

Для управления этой проблемой сборка C++ использует другой метод для поддержки добавочных сборок. Большинство целевых объектов не указывают входные и выходные данные, а в результате всегда выполняются во время сборки. Задачи, вызываемые целевыми объектами, записывают сведения обо всех входных и выходных данных в файлы tlog с расширением TLOG. Файлы TLOG используются более поздними сборками для проверка изменения и необходимости перестроения и актуальности. Tlog-файлы также являются единственным источником для актуальной сборки по умолчанию проверка в интегрированной среде разработки.

Чтобы определить все входные и выходные данные, задачи собственного средства используют tracker.exe и класс FileTracker , предоставляемый MSBuild.

Microsoft.Build.CPPTasks.Common.dll определяет общедоступный абстрактный базовый TrackedVCToolTask класс. Большинство собственных задач инструментов являются производными от этого класса.

Начиная с Visual Studio 2017 с обновлением 15.8, можно использовать задачу, реализованную GetOutOfDateItems в Microsoft.Cpp.Common.Tasks.dll, для создания Tlog-файлов для пользовательских целевых объектов с известными входными и выходными данными. Кроме того, их можно создать с помощью WriteLinesToFile задачи. Пример см. в $(VCTargetsPath)\целевом объекте _WriteMasmTlogs BuildCustomizations\masm.target.

TLOG-файлы

Существует три типа файлов TLOG: чтение, запись и командная строка. Чтение и запись tlog-файлов используются добавочными сборками и актуальными проверка в интегрированной среде разработки. Файлы Tlog командной строки используются только в добавочных сборках.

MSBuild предоставляет следующие вспомогательные классы для чтения и записи tlog-файлов:

Класс FlatTrackingData можно использовать для доступа как к файлам чтения, так и записи tlog и идентификации входных данных, которые являются более новыми, чем выходные данные, или если выходные данные отсутствуют. Он используется в актуальном проверка.

Файлы TLOG командной строки содержат сведения о командных строках, используемых в сборке. Они используются только для добавочных сборок, а не актуальных проверка, поэтому внутренний формат определяется задачей MSBuild, которая создает их.

Чтение формата TLOG

Чтение tlog-файлов (*.read.*.tlog) содержит сведения о исходных файлах и их зависимостях.

Курсор (^) в начале строки указывает один или несколько источников. Источники с одинаковыми зависимостями разделяются вертикальной полосой (|).

Файлы зависимостей перечислены после источников, каждая из которых имеет собственную строку. Все имена файлов являются полными путями.

Например, предположим, что источники проекта находятся в F:\test\ConsoleApplication1\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) подключает источники и выходные данные.

Курсор (^) в начале строки указывает один или несколько источников. Несколько источников разделены вертикальной полосой (|).

Выходные файлы, созданные из источников, должны быть перечислены после источников, каждый из которых имеет собственную строку. Все имена файлов должны быть полными путями.

Например, для простого проекта ConsoleApplication с дополнительным исходным файлом Class1.cpp файл 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

Сборка во время разработки

В интегрированной среде разработки проекты .vcxproj используют набор целевых объектов MSBuild для получения дополнительных сведений из проекта и повторного создания выходных файлов. Некоторые из этих целевых объектов используются только в сборках во время разработки, но многие из них используются как в обычных сборках, так и во время разработки.

Общие сведения о сборках во время разработки см. в документации CPS по сборкам времени разработки. Эта документация частично применима только к проектам Visual C++.

Compile И целевые CompileDesignTime объекты, упоминание в документации по сборкам во время разработки, никогда не выполняются для проектов .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'" во всех операциях, которые используются только для обычных сборок, а не для сборок во время разработки.

Целевые объекты во время разработки, создающие источники

Эта функция отключена по умолчанию для собственных проектов Desktop и в настоящее время не поддерживается в кэшированных проектах.

Если GeneratorTarget метаданные определены для элемента проекта, целевой объект выполняется автоматически как при загрузке проекта, так и при изменении исходного файла.

Например, чтобы автоматически создавать файлы CPP или H из XAML-файлов, $(VSInstallDir)\файлы MSBuild\Microsoft WindowsXaml\версии 16.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 Чтобы получить несохраняемое содержимое исходных файлов, целевые объекты и задачи должны быть зарегистрированы как MsbuildHostObjects для указанных проектов в pkgdef:

\[$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++ в интегрированной среде разработки Visual Studio

Система проектов Visual C++ основана на системе проектов VS и использует точки расширяемости. Однако реализация иерархии проектов зависит от Visual C++ и не основана на CPS, поэтому расширяемость иерархии ограничена элементами проекта.

Страницы свойств проекта

Общие сведения о проектировании см. в разделе "Многоцелевой платформы для проектов VC++".

Простыми словами страницы свойств, которые отображаются в диалоговом окне "Свойства проекта" для проекта C++, определяются файлами правил . Файл правила задает набор свойств, отображаемых на странице свойств, и как и где они должны быть сохранены в файле проекта. Файлы правил — это XML-файлы, использующие формат Xaml. Типы, используемые для сериализации, описаны в 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 определяет, как правило отображается в диалоговом окне "Страницы свойств". Атрибут может иметь одно из следующих значений:

Атрибут Description
generic Все свойства отображаются на одной странице в заголовках категорий
Правило может отображаться для Project и PropertySheet контекстов, но не File.

Пример: $(VCTargetsPath)\1033\general.xml
tool Категории отображаются как вложенные страницы.
Правило может отображаться во всех контекстах: ProjectPropertySheet и File.
Правило отображается в свойствах проекта, только если проект содержит элементы с ItemType определенным в Rule.DataSource, если имя правила не включено в группу ProjectTools элементов.

Пример: $(VCTargetsPath)\1033\clang.xml
debugger Страница отображается как часть страницы отладки.
Категории в настоящее время игнорируются.
Имя правила должно соответствовать атрибуту объекта MEF средства запуска отладки ExportDebugger .

Пример: $(VCTargetsPath)\1033\debugger_local_windows.xml
custom Пользовательский шаблон. Имя шаблона должно соответствовать ExportPropertyPageUIFactoryProvider атрибуту PropertyPageUIFactoryProvider объекта MEF. См. раздел Microsoft.VisualStudio.ProjectSystem.Designers.Properties.IPropertyPageUIFactoryProvider.

Пример: $(VCTargetsPath)\1033\userMacros.xml

Если правило использует один из шаблонов сетки свойств, оно может использовать эти точки расширяемости для его свойств:

Расширение правила

Если вы хотите использовать существующее правило, но необходимо добавить или удалить (то есть скрыть) всего несколько свойств, можно создать правило расширения.

Переопределение правила

Возможно, вы хотите, чтобы набор инструментов использовал большинство правил по умолчанию проекта, но заменить только один или несколько из них. Например, предположим, что вы хотите изменить правило C/C++, чтобы отобразить различные коммутаторы компилятора. Вы можете указать новое правило с тем же именем и отображаемое имя, что и существующее правило, и включить его в PropertyPageSchema группу элементов после импорта целевых объектов cpp по умолчанию. В проекте используется только одно правило с заданным именем, а последнее включено в группу PropertyPageSchema элементов.

Номенклатуры проекта

Xml-файл ProjectItemsSchema.xml определяет ContentType и ItemType значения элементов, которые обрабатываются как элементы проекта, и определяет FileExtension элементы, чтобы определить, в какую группу элементов добавляется новый файл.

Файл ProjectItemsSchema по умолчанию найден в $(VCTargetsPath)\файле ProjectItemsSchema.xml 1033\. Чтобы расширить его, необходимо создать файл схемы с новым именем, например 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. Отключите актуальный проверка по умолчанию, добавив NoVCDefaultBuildUpToDateCheckProvider возможность в файл Toolset.targets:

    <ItemGroup>
      <ProjectCapability Include="NoVCDefaultBuildUpToDateCheckProvider" />
    </ItemGroup>
    
  2. Реализуйте собственный IBuildUpToDateCheckProvider.

Обновление проекта

Обновление проекта .vcxproj по умолчанию

Средство обновления проекта .vcxproj по умолчанию изменяет PlatformToolsetApplicationTypeRevisionверсию набора инструментов MSBuild и платформа .NET Framework. Последние два всегда изменяются на значения по умолчанию версии Visual Studio, но PlatformToolsetApplicationTypeRevision их можно управлять специальными свойствами MSBuild.

Обновление использует эти критерии, чтобы определить, может ли проект быть обновлен или нет:

  1. Для проектов, определяющих ApplicationType и ApplicationTypeRevision, есть папка с более высоким номером редакции, чем текущая.

  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>

Кэш проектов и расширяемость

Чтобы повысить производительность при работе с крупными решениями C++ в Visual Studio 2017, был представлен кэш проекта. Она реализована как база данных SQLite, заполненная данными проекта, а затем используется для загрузки проектов без загрузки проектов MSBuild или CPS в память.

Так как для проектов .vcxproj, загруженных из кэша, отсутствуют объекты CPS, компоненты MEF расширения, импортируемые UnconfiguredProject или ConfiguredProject не могут быть созданы. Для поддержки расширяемости кэш проекта не используется при обнаружении того, используется ли проект (или, скорее всего, используется) расширения MEF.

Эти типы проектов всегда загружаются и имеют объекты CPS в памяти, поэтому для них создаются все расширения MEF:

  • Запуск проектов

  • Проекты с пользовательским обновлением проекта, то есть определяют VCProjectUpgraderObjectName свойство.

  • Проекты, которые не предназначены для Классических Windows, то есть определяют ApplicationType свойство

  • Проекты общих элементов (.vcxitems) и все проекты, ссылающиеся на них путем импорта проектов .vcxitems.

Если ни одно из этих условий не обнаружено, создается кэш проекта. Кэш включает все данные из проекта MSBuild, необходимые для ответа на get запросы к VCProjectEngine интерфейсам. Это означает, что все изменения на уровне файла MSBuild, выполненные расширением, должны работать только в проектах, загруженных из кэша.

Доставка расширения

Сведения о создании файлов VSIX см. в разделе "Доставка расширений Visual Studio". Сведения о том, как добавлять файлы в специальные расположения установки, например для добавления файлов $(VCTargetsPath)в папку расширений, см. в разделе "Установка за пределами папки расширений".

Дополнительные ресурсы

Система сборки Майкрософт (MSBuild) предоставляет подсистему сборки и расширяемый формат XML для файлов проекта. Вы должны ознакомиться с основными понятиями MSBuild и способом работы MSBuild для Visual C++ для расширения системы проектов Visual C++.

Платформа управляемого расширения (MEF) предоставляет API расширения, используемые CPS и системой проектов Visual C++. Общие сведения о том, как MEF использует CPS, см. в разделе CPS и MEF в обзоре VSProjectSystem meF.

Вы можете настроить существующую систему сборки, чтобы добавить шаги сборки или новые типы файлов. Дополнительные сведения см. в обзоре MSBuild (Visual C++) и работе со свойствами проекта.