Integración del conjunto de herramientas y extensibilidad del sistema de Visual Studio C++ Project
El sistema de proyectos de Visual C++ se usa para archivos .vcxproj. Se basa en el Visual Studio Common Project System (CPS) y proporciona puntos adicionales específicos de C++ para facilitar la integración de nuevos conjuntos de herramientas, arquitecturas de compilación y plataformas de destino.
Estructura de objetivos de MSBuild de C++
Todos los archivos .vcxproj importan estos archivos:
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
Estos archivos definen poco por sí mismos. En su lugar, importan otros archivos en función de estos valores de propiedad:
$(ApplicationType)
Ejemplos: Tienda Windows, Android, Linux
$(ApplicationTypeRevision)
Debe ser una cadena de versión válida, con el formato major.minor[.build[.revision]].
Ejemplos: 1.0, 10.0.0.0
$(Platform)
La arquitectura de compilación, denominada "Plataforma" por motivos históricos.
Ejemplos: Win32, x86, x64, ARM
$(PlatformToolset)
Ejemplos: v140, v141, v141_xp, llvm
Estos valores de propiedad especifican nombres de carpeta en la carpeta raíz $(VCTargetsPath)
:
$(VCTargetsPath)
\
tipo de aplicación\
$(ApplicationType)
\
$(ApplicationTypeRevision)
\
Plataformas\
$(Platform)
\
PlatformToolsets\
$(PlatformToolset)
Plataformas\
$(Platform)
\
PlatformToolsets\
$(PlatformToolset)
La carpeta $(VCTargetsPath)
\Platforms\ se usa cuando $(ApplicationType)
está vacía, para proyectos de escritorio de Windows.
Adición de un nuevo conjunto de herramientas de plataforma
Para agregar un nuevo conjunto de herramientas, por ejemplo, "MyToolset" para la plataforma Win32 existente, cree una carpeta MyToolset en $(VCTargetsPath)
\Platforms\Win32\PlatformToolsets\y cree Toolset.props y Toolset.targets archivos.
Cada nombre de carpeta PlatformToolsets aparece en el cuadro de diálogo Propiedades del proyecto como un Conjunto de herramientas de plataforma disponible para la plataforma especificada, como se muestra aquí:
Cree carpetas MyToolset similares y archivos Toolset.props y Toolset.targets en cada carpeta de plataforma existente que admite este conjunto de herramientas.
Adición de una nueva plataforma
Para agregar una nueva plataforma, por ejemplo, "MyPlatform", cree una carpeta MyPlatform en $(VCTargetsPath)
\Platforms\y cree archivos Platform.default.props, Platform.propsy Platform.targets. Cree también una carpeta $(VCTargetsPath)
\Platforms\MyPlatform\PlatformToolsets\ y cree al menos un conjunto de herramientas en él.
Todos los nombres de carpeta bajo la carpeta Platforms para cada $(ApplicationType)
y $(ApplicationTypeRevision)
aparecen en el IDE como opciones Platform disponibles para un proyecto.
Agregar un nuevo tipo de aplicación
Para agregar un nuevo tipo de aplicación, cree una carpeta MyApplicationType en $(VCTargetsPath)
\Application Type\ y cree un archivo Defaults.props en él. Se requiere al menos una revisión para un tipo de aplicación, por lo que también cree una carpeta $(VCTargetsPath)
\Application Type\MyApplicationType\1.0 y cree un archivo Defaults.props en él. También debe crear una carpeta $(VCTargetsPath)
\ApplicationType\MyApplicationType\1.0\Platforms y crear al menos una plataforma en ella.
Las propiedades $(ApplicationType)
y $(ApplicationTypeRevision)
no se muestran en la interfaz de usuario. Se definen en las plantillas de proyecto y no se pueden cambiar después de crear el proyecto.
Árbol de importación de .vcxproj
Un árbol simplificado de importaciones para propiedades y archivos de destinos de Microsoft C++ tiene el siguiente aspecto:
$(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
Los proyectos de escritorio de Windows no definen $(ApplicationType)
, por lo que solo importan
$(VCTargetsPath)
\ Microsoft.Cpp.Default.props
$(MSBuildExtensionsPath)
\$(MSBuildToolsVersion)
\Microsoft.Common.props
$(VCTargetsPath)
\ImportBefore\Default\*.props
$(VCTargetsPath)
\Platforms\$(Platform)
\Platform.default.props
$(VCTargetsPath)
\ImportAfter\Default\*.props
Usaremos la propiedad $(_PlatformFolder)
para almacenar las ubicaciones de las carpetas de la plataforma $(Platform)
. This property is
$(VCTargetsPath)
\Platforms\$(Platform)
para aplicaciones de escritorio de Windows y
$(VCTargetsPath)
\Tipo de Aplicación\$(ApplicationType)
\$(ApplicationTypeRevision)
\Plataformas\$(Platform)
para todo lo demás.
Los archivos props se importan en este orden:
$(VCTargetsPath)
\Microsoft.Cpp.props
$(_PlatformFolder)
\Platform.props
$(VCTargetsPath)
\ Microsoft.Cpp.Platform.props
$(_PlatformFolder)
\ImportBefore\*.props
$(_PlatformFolder)
\PlatformToolsets\$(PlatformToolset)
\Toolset.props
$(_PlatformFolder)
\ImportAfter\*.props
Los archivos de destino se importan en este orden:
$(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
Si necesita definir algunas propiedades predeterminadas para el conjunto de herramientas, puede agregar archivos a las carpetas ImportBefore e ImportAfter adecuadas.
Creación de archivos Toolset.props y Toolset.targets
Toolset.props y Toolset.targets archivos tienen control total sobre lo que sucede durante una compilación cuando se usa este conjunto de herramientas. También pueden controlar los depuradores disponibles, parte de la interfaz de usuario del IDE, como el contenido en el cuadro de diálogo de las páginas de propiedades, y otros aspectos del comportamiento del proyecto.
Aunque un conjunto de herramientas puede invalidar todo el proceso de compilación, normalmente solo quiere que el conjunto de herramientas modifique o agregue algunos pasos de compilación, o para usar diferentes herramientas de compilación, como parte de un proceso de compilación existente. Para lograr este objetivo, hay una serie de propiedades comunes y archivos de destino que el conjunto de herramientas puede importar. En función de lo que quiera que haga el conjunto de herramientas, estos archivos pueden ser útiles para usarlos como importaciones o como ejemplos:
$(VCTargetsPath)
\Microsoft.CppCommon.targetsEste archivo define las partes principales del proceso de compilación nativo y también importa:
$(VCTargetsPath)
\Microsoft.CppBuild.targets$(VCTargetsPath)
\Microsoft.BuildSteps.targets$(MSBuildToolsPath)
\Microsoft.Common.Targets
$(VCTargetsPath)
\ Microsoft.Cpp.Common.propsEstablece los valores predeterminados de los conjuntos de herramientas que usan los compiladores de Microsoft y Windows de destino.
$(VCTargetsPath)
\ Microsoft.Cpp.WindowsSDK.propsEste archivo determina la ubicación de Windows SDK y define algunas propiedades importantes para las aplicaciones destinadas a Windows.
Integración de destinos específicos del conjunto de herramientas con el proceso de compilación predeterminado de C++
El proceso de compilación predeterminado de C++ se define en Microsoft.CppCommon.targets. Los destinos no llaman a ninguna herramienta de compilación específica; especifican los pasos de compilación principales, su orden y sus dependencias.
La compilación de C++ tiene tres pasos principales, que se representan mediante los siguientes destinos:
BuildGenerateSources
BuildCompile
BuildLink
Dado que cada paso de compilación se puede ejecutar de forma independiente, los destinos que se ejecutan en un paso no pueden depender de los grupos de elementos y las propiedades definidas en los destinos que se ejecutan como parte de un paso diferente. Esta división permite ciertas optimizaciones de rendimiento de compilación. Aunque no se utiliza por defecto, se recomienda igualmente respetar esta separación.
Los objetivos que se ejecutan en cada paso están controlados por estas propiedades:
$(BuildGenerateSourcesTargets)
$(BuildCompileTargets)
$(BeforeBuildLinkTargets)
Cada paso también tiene propiedades de Antes y Después.
<Target
Name="_BuildGenerateSourcesAction"
DependsOnTargets="$(CommonBuildOnlyTargets);$(BeforeBuildGenerateSourcesTargets);$(BuildGenerateSourcesTargets);$(AfterBuildGenerateSourcesTargets)" />
<Target
Name="\_BuildCompileAction"
DependsOnTargets="$(CommonBuildOnlyTargets);$(BeforeBuildCompileTargets);$(BuildCompileTargets);$(AfterBuildCompileTargets)" />
<Target
Name="\_BuildLinkAction"
DependsOnTargets="$(CommonBuildOnlyTargets);$(BeforeBuildLinkTargets);$(BuildLinkTargets);$(AfterBuildLinkTargets)" />
Consulte el archivo Microsoft.CppBuild.targets para obtener ejemplos de los objetivos que se incluyen en cada paso:
<BuildCompileTargets Condition="'$(ConfigurationType)'\!='Utility'">
$(BuildCompileTargets);
_ClCompile;
_ResGen;
_ResourceCompile;
$(BuildLibTargets);
</BuildCompileTargets>
Si observa los objetivos, como _ClCompile
, verá que no hacen nada directamente por ellos mismos, sino que dependen de otros objetivos, incluidos ClCompile
:
<Target Name="_ClCompile"
DependsOnTargets="$(BeforeClCompileTargets);$(ComputeCompileInputsTargets);MakeDirsForCl;ClCompile;$(AfterClCompileTargets)" >
</Target>
ClCompile
y otros destinos específicos de la herramienta de compilación se definen como destinos vacíos en Microsoft.CppBuild.targets:
<Target Name="ClCompile"/>
Dado que el destino de ClCompile
está vacío, a menos que un conjunto de herramientas lo invalide, no se realiza ninguna acción de compilación real. Los destinos del conjunto de herramientas pueden sobrescribir el destino ClCompile
; es decir, pueden contener una definición alternativa de ClCompile
después de importar Microsoft.CppBuild.targets:
<Target Name="ClCompile"
Condition="'@(ClCompile)' != ''"
DependsOnTargets="SelectClCompile">
<!-- call some MSBuild tasks -->
</Target>
A pesar de su nombre, que se creó antes de que Visual Studio implementara compatibilidad multiplataforma, el objetivo ClCompile
no está obligado a llamar a CL.exe. También puede llamar a Clang, gcc u otros compiladores mediante las tareas adecuadas de MSBuild.
El destino ClCompile
no debe tener ninguna dependencia, excepto el destino SelectClCompile
, que es necesario para que el comando de compilación de archivo único funcione en el IDE.
Tareas de MSBuild que se van a usar en destinos del conjunto de herramientas
Para invocar una herramienta de compilación real, el destino debe llamar a una tarea de MSBuild. Hay una tarea exec básica que permite especificar una línea de comandos que se va a ejecutar. Sin embargo, las herramientas de compilación suelen tener muchas opciones, entradas y salidas para realizar un seguimiento de las compilaciones incrementales, por lo que tiene más sentido tener tareas especiales para ellas. Por ejemplo, la tarea CL
traduce las propiedades de MSBuild en conmutadores de CL.exe, los escribe en un archivo de respuesta y llama a CL.exe. También realiza un seguimiento de todos los archivos de entrada y salida para compilaciones incrementales posteriores. Para obtener más información, consulte Compilaciones incrementales y comprobaciones actualizadas.
El Microsoft.Cpp.Common.Tasks.dll implementa estas tareas:
BSCMake
CL
ClangCompile
(conmutadores clang-gcc)LIB
LINK
MIDL
Mt
RC
XDCMake
CustomBuild
(como Exec, pero con seguimiento de entrada y salida)SetEnv
GetOutOfDateItems
Si tiene una herramienta que realiza la misma acción que una herramienta existente y que tiene modificadores de línea de comandos similares (como clang-cl y CL), puede usar la misma tarea para ambas.
Si necesita crear una nueva tarea para una herramienta de compilación, puede elegir entre las siguientes opciones:
Si usa esta tarea rara vez o si unos segundos no importan para la compilación, puede usar las tareas "insertadas" de MSBuild:
Tarea Xaml (una regla de compilación personalizada)
Para obtener un ejemplo de una declaración de tarea Xaml, consulta
$(VCTargetsPath)
\BuildCustomizations\masm.xml, y para su uso, consulta$(VCTargetsPath)
\BuildCustomizations\masm.targets.
Si desea mejorar el rendimiento de las tareas o simplemente necesita una funcionalidad más compleja, use el proceso normal de escritura de tareas de MSBuild.
Si no todas las entradas y salidas de la herramienta se muestran en la línea de comandos de la herramienta, como en los casos de
CL
,MIDL
yRC
, y si desea el seguimiento automático de archivos de entrada y salida y creación de archivos .tlog, derive la tarea de la claseMicrosoft.Build.CPPTasks.TrackedVCToolTask
. En la actualidad, aunque hay documentación para la clase ToolTask base, no hay ejemplos ni documentación para los detalles de la claseTrackedVCToolTask
. Si esto es de especial interés, haga oír su voz en una solicitud en Developer Community.
Compilaciones incrementales y comprobaciones actualizadas
Los destinos de compilación incremental de MSBuild predeterminados usan atributos Inputs
y Outputs
. Si los especifica, MSBuild llama al destino solo si alguna de las entradas tiene una marca de tiempo más reciente que todas las salidas. Dado que los archivos de origen suelen incluir o importar otros archivos, y las herramientas de compilación generan diferentes salidas en función de las opciones de la herramienta, es difícil especificar todas las entradas y salidas posibles en destinos de MSBuild.
Para administrar este problema, la compilación de C++ usa una técnica diferente para admitir compilaciones incrementales. La mayoría de los destinos no especifican entradas y salidas y, como resultado, siempre se ejecutan durante la compilación. Las tareas llamadas por los destinos escriben información sobre todas las entradas y salidas en archivos tlog que tienen una extensión .tlog. Las compilaciones posteriores usan los archivos .tlog para comprobar lo que ha cambiado y se debe volver a generar y lo que es up-to-date. Los archivos .tlog son también la única fuente para la verificación de fecha de la compilación predeterminada up-toen el IDE.
Para determinar todas las entradas y salidas, las tareas de herramientas nativas usan tracker.exe y la clase de FileTracker proporcionada por MSBuild.
Microsoft.Build.CPPTasks.Common.dll define la clase base TrackedVCToolTask
abstracta pública. La mayoría de las tareas de herramientas nativas se derivan de esta clase.
A partir de la actualización 15.8 de Visual Studio 2017, puede usar la tarea de GetOutOfDateItems
implementada en Microsoft.Cpp.Common.Tasks.dll para generar archivos .tlog para destinos personalizados con entradas y salidas conocidas.
Como alternativa, puede crearlos mediante la tarea WriteLinesToFile
. Consulte el destino de _WriteMasmTlogs
en $(VCTargetsPath)
\BuildCustomizations\masm.targets como ejemplo.
Archivos .tlog
Hay tres tipos de archivos .tlog: leer, escribiry línea de comandos. Las compilaciones incrementales usan los archivos .tlog de lectura y escritura y la comprobación actualizada en el IDE. Los archivos .tlog de la línea de comandos solo se usan en compilaciones incrementales.
MSBuild proporciona estas clases auxiliares para leer y escribir archivos .tlog:
La clase FlatTrackingData se puede usar para tener acceso a archivos .tlog de lectura y escritura e identificar las entradas que son más recientes que las salidas, o si falta una salida. Se usa en la comprobación actualizada.
Los archivos .tlog de la línea de comandos contienen información sobre las líneas de comandos usadas en la compilación. Solo se usan para compilaciones incrementales, no comprobaciones actualizadas, por lo que el formato interno viene determinado por la tarea de MSBuild que las genera.
Leer el formato .tlog
Los archivos de lectura .tlog (*.read.*.tlog) contienen información sobre los archivos de origen y sus dependencias.
Un caret (^) al principio de una línea indica una o varias fuentes. Las fuentes que comparten las mismas dependencias están separadas por una barra vertical (|).
Los archivos de dependencia se muestran después de los orígenes, cada uno en su propia línea. Todos los nombres de archivo son rutas de acceso completas.
Por ejemplo, supongamos que los orígenes del proyecto se encuentran en F:\test\ConsoleApplication1\ConsoleApplication1. Si el archivo de origen, Class1.cpp, tiene estos elementos,
#include "stdafx.h" //precompiled header
#include "Class1.h"
a continuación, el archivo CL.read.1.tlog contiene el archivo de origen seguido de sus dos dependencias:
^F:\TEST\CONSOLEAPPLICATION1\CONSOLEAPPLICATION1\CLASS1.CPP
F:\TEST\CONSOLEAPPLICATION1\CONSOLEAPPLICATION1\DEBUG\CONSOLEAPPLICATION1.PCH
F:\TEST\CONSOLEAPPLICATION1\CONSOLEAPPLICATION1\CLASS1.H
No es necesario escribir nombres de archivo en mayúsculas, pero es una comodidad para algunas herramientas.
Escribir formato .tlog
Los archivos de escritura .tlog (*.write.*.tlog) conectan orígenes y salidas.
Un caret (^) al principio de una línea indica una o más fuentes. Varios fuentes están separados por una barra vertical (|).
Los archivos de salida creados a partir de las fuentes deben aparecer después de las fuentes, cada uno en su propia línea. Todos los nombres de archivo deben ser rutas de acceso completas.
Por ejemplo, para un proyecto consoleApplication simple que tenga un archivo de origen adicional Class1.cpp, el archivo link.write.1.tlog puede contener:
^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
Compilación en tiempo de diseño
En el IDE, los proyectos .vcxproj usan un conjunto de objetivos de MSBuild para obtener información adicional del proyecto y volver a generar archivos de salida. Algunos de estos objetivos solo se utilizan en compilaciones en tiempo de diseño, pero muchos de ellos se emplean tanto en compilaciones normales como en compilaciones en tiempo de diseño.
Para obtener información general sobre las compilaciones en tiempo de diseño, consulte la documentación sobre compilaciones en tiempo de diseño de CPS. Esta documentación solo es aplicable parcialmente a proyectos de Visual C++.
Los destinos CompileDesignTime
y Compile
mencionados en la documentación de compilaciones en tiempo de diseño nunca se ejecutan para proyectos de .vcxproj. Los proyectos de Visual C++ .vcxproj usan diferentes objetivos de tiempo de diseño para obtener información de IntelliSense.
Destinos en tiempo de diseño para la información de IntelliSense
Los destinos de tiempo de diseño usados en proyectos .vcxproj se definen en $(VCTargetsPath)
\Microsoft.Cpp.DesignTime.targets.
El destino de GetClCommandLines
recopila opciones del compilador para IntelliSense:
<Target
Name="GetClCommandLines"
Returns="@(ClCommandLines)"
DependsOnTargets="$(DesignTimeBuildInitTargets);$(ComputeCompileInputsTargets)">
DesignTimeBuildInitTargets
: destinos solo en tiempo de diseño, necesarios para la inicialización de compilación en tiempo de diseño. Entre otras cosas, estos destinos deshabilitan parte de la funcionalidad de compilación normal para mejorar el rendimiento.ComputeCompileInputsTargets
: un conjunto de destinos que modifica las opciones y elementos del compilador. Estos destinos se ejecutan tanto en tiempo de diseño como en compilaciones normales.
El destino llama a la tarea CLCommandLine
para crear la línea de comandos que se usará para IntelliSense. De nuevo, a pesar de su nombre, puede controlar no solo las opciones cl, sino también las opciones de Clang y gcc. El tipo de opciones del compilador se controla mediante la propiedad ClangMode
.
Actualmente, la línea de comandos generada por la tarea CLCommandLine
siempre usa conmutadores CL (incluso en modo Clang) porque son más fáciles para que el motor de IntelliSense los analice.
Si va a agregar un destino que se ejecuta antes de la compilación, ya sea normal o en tiempo de diseño, asegúrese de que no interrumpe las compilaciones en tiempo de diseño ni afecta al rendimiento. La manera más sencilla de probar su objetivo es abrir una línea de comandos para desarrolladores y ejecutar este comando:
msbuild /p:SolutionDir=*solution-directory-with-trailing-backslash*;Configuration=Debug;Platform=Win32;BuildingInsideVisualStudio=true;DesignTimebuild=true /t:\_PerfIntellisenseInfo /v:d /fl /fileloggerparameters:PerformanceSummary \*.vcxproj
Este comando genera un registro de compilación detallado, msbuild.log, que tiene un resumen de rendimiento para los destinos y las tareas al final.
Asegúrese de usar Condition ="'$(DesignTimeBuild)' != 'true'"
en todas las operaciones que solo tengan sentido para las compilaciones normales y no para las compilaciones en tiempo de diseño.
Objetivos en tiempo de diseño que generan códigos fuente
Esta característica está deshabilitada de forma predeterminada para proyectos nativos de escritorio y no se admite actualmente en proyectos almacenados en caché.
Si se definen metadatos GeneratorTarget
para un elemento del proyecto, el objetivo se ejecuta automáticamente tanto al cargar el proyecto como al cambiar el archivo de origen.
Por ejemplo, para generar automáticamente archivos .cpp o .h a partir de archivos .xaml, los archivos de $(VSInstallDir)
\MSBuild\Microsoft\WindowsXaml\v16.0\*\Microsoft.Windows.UI.Xaml.CPP.Targets definen estas entidades:
<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>
Para usar Task.HostObject
para obtener el contenido no guardado de los archivos de origen, los destinos y la tarea deben registrarse como MsbuildHostObjects para los proyectos especificados en una pkgdef:
\[$RootKey$\\Projects\\{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\\MSBuildHostObjects\]
\[$RootKey$\\Projects\\{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\\MSBuildHostObjects\\DesignTimeMarkupCompilationCT;CompileXaml\]
@="{83046B3F-8984-444B-A5D2-8029DEE2DB70}"
Extensibilidad del proyecto de Visual C++ en el IDE de Visual Studio
El sistema de proyectos de Visual C++ se basa en VS Project Systemy usa sus puntos de extensibilidad. Sin embargo, la implementación de la jerarquía del proyecto es específica de Visual C++ y no se basa en CPS, por lo que la extensibilidad de la jerarquía se limita a los elementos del proyecto.
Páginas de propiedades del proyecto
Para obtener información general de diseño, consulte Framework Multi-Targeting for VC++ Projects.
En términos simples, las páginas de propiedades que ve en el cuadro de diálogo Propiedades del proyecto para un proyecto de C++ se definen mediante archivos regla. Un archivo de reglas especifica un conjunto de propiedades que se van a mostrar en una página de propiedades y cómo y dónde deben guardarse en el archivo de proyecto. Los archivos .xml son archivos de regla que usan el formato Xaml. Los tipos usados para serializarlos se describen en Microsoft.Build.Framework.XamlTypes. Para obtener más información sobre el uso de archivos de reglas en proyectos, consulte los archivos de reglas XML de página de propiedades.
Los archivos de regla se deben agregar al grupo de elementos de PropertyPageSchema
:
<ItemGroup>
<PropertyPageSchema Include="$(VCTargetsPath)$(LangID)\general.xml;"/>
<PropertyPageSchema Include="$(VCTargetsPath)$(LangID)\general_file.xml">
<Context>File</Context>
</PropertyPageSchema>
</ItemGroup>
Context
la visibilidad de las reglas de límites de metadatos, que también se controla mediante el tipo de regla, y puede tener uno de estos valores:
Project
| File
| PropertySheet
CPS admite otros valores para el tipo de contexto, pero no se usan en proyectos de Visual C++.
Si la regla debe estar visible en más de un contexto, use punto y coma (;) para separar los valores de contexto, como se muestra aquí:
<PropertyPageSchema Include="$(MyFolder)\MyRule.xml">
<Context>Project;PropertySheet</Context>
</PropertyPageSchema>
Formato de regla y tipos principales
El formato de regla es sencillo, por lo que en esta sección solo se describen los atributos que afectan al aspecto de la regla en la interfaz de usuario.
<Rule
Name="ConfigurationGeneral"
DisplayName="General"
PageTemplate="generic"
Description="General"
xmlns="http://schemas.microsoft.com/build/2009/properties">
El atributo PageTemplate
define cómo se muestra la regla en las páginas de propiedades del cuadro de diálogo. El atributo puede tener uno de estos valores:
Atributo | Descripción |
---|---|
generic |
Todas las propiedades se muestran en una página en encabezados de categoría La regla puede estar visible para contextos de Project y PropertySheet , pero no File .Ejemplo: $(VCTargetsPath) \1033\general.xml |
tool |
Las categorías se muestran como subpáginas. La regla puede estar visible en todos los contextos: Project , PropertySheet y File .La regla solo está visible en Propiedades del proyecto si el proyecto tiene elementos con el ItemType definido en Rule.DataSource , a menos que el nombre de la regla se incluya en el grupo de elementos ProjectTools .Ejemplo: $(VCTargetsPath) \1033\clang.xml |
debugger |
La página se muestra como parte de la página de depuración. Actualmente se omiten las categorías. El nombre de la regla debe coincidir con el atributo ExportDebugger del objeto MEF del Lanzador de depuración.Ejemplo: $(VCTargetsPath) \1033\debugger_local_windows.xml |
custom | Plantilla personalizada. El nombre de la plantilla debe coincidir con el atributo ExportPropertyPageUIFactoryProvider del objeto PropertyPageUIFactoryProvider MEF. Consulte Microsoft.VisualStudio.ProjectSystem.Designer.Properties.IPropertyPageUIFactoryProvider.Ejemplo: $(VCTargetsPath) \1033\userMacros.xml |
Si la regla usa una de las plantillas basadas en Property Grid, puede usar estos puntos de extensibilidad para sus propiedades:
Extensión de una regla
Si desea usar una regla existente, pero necesita agregar o quitar (es decir, ocultar) solo algunas propiedades, puede crear una regla de extensión de .
Invalidación de una regla
Quizás quiera que el conjunto de herramientas use la mayoría de las reglas predeterminadas del proyecto, pero reemplace solo una o algunas de ellas. Por ejemplo, supongamos que solo desea cambiar la regla de C/C++ para mostrar diferentes opciones del compilador. Usted puede proporcionar una nueva regla con el mismo nombre y nombre para mostrar que la regla existente e incluirla en el grupo de elementos de PropertyPageSchema
después de la importación de objetivos predeterminados de C++. Solo se usa una regla con un nombre determinado en el proyecto y la última incluida en el grupo de elementos de PropertyPageSchema
gana.
Elementos del proyecto
El archivo ProjectItemsSchema.xml define los valores de ContentType
y ItemType
para Elementos que se tratan como elementos de proyecto y define FileExtension
elementos para determinar a qué grupo de elementos se agrega un nuevo archivo.
El archivo ProjectItemsSchema predeterminado se encuentra en $(VCTargetsPath)
\1033\ProjectItemsSchema.xml. Para ampliarlo, debe crear un archivo de esquema con un nuevo nombre, como 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>
A continuación, en el archivo de destinos, agregue:
<ItemGroup>
<PropertyPageSchema Include="MyProjectItemsSchema.xml"/>
</ItemGroup>
Ejemplo: $(VCTargetsPath)
\BuildCustomizations\masm.xml
Depuradores
El servicio de depuración en Visual Studio admite la extensibilidad para el motor de depuración. Para obtener más información, consulte estos ejemplos:
Para especificar los motores de depuración y otras propiedades para la sesión de depuración, debe implementar un componente MEF de selector de depuración y agregar una regla de debugger
. Para obtener un ejemplo, consulte el archivo $(VCTargetsPath)
\1033\debugger_local_windows.xml.
Desplegar
Los proyectos .vcxproj usan la extensibilidad de Visual Studio Project System para Implementar proveedores.
Comprobación actualizada
De forma predeterminada, la comprobación de compilación up-to-date requiere que durante la compilación se creen en la carpeta $(TlogLocation)
los archivos de lectura .tlog y los archivos de escritura .tlog para todas las entradas y salidas de compilación.
Para usar una comprobación actualizada personalizada:
Deshabilite la comprobación actualizada predeterminada agregando la funcionalidad
NoVCDefaultBuildUpToDateCheckProvider
en el archivo Toolset.targets:<ItemGroup> <ProjectCapability Include="NoVCDefaultBuildUpToDateCheckProvider" /> </ItemGroup>
Implemente su propio IBuildUpToDateCheckProvider.
Actualización del proyecto
Actualizador predeterminado de proyecto .vcxproj
El actualizador predeterminado del proyecto .vcxproj modifica PlatformToolset
, ApplicationTypeRevision
, la versión del conjunto de herramientas MSBuild y el .NET Framework. Los dos últimos siempre se cambian a los valores predeterminados de la versión de Visual Studio, pero PlatformToolset
y ApplicationTypeRevision
se pueden controlar mediante propiedades especiales de MSBuild.
El actualizador usa estos criterios para decidir si un proyecto se puede actualizar o no:
Para los proyectos que definen
ApplicationType
yApplicationTypeRevision
, hay una carpeta con un número de revisión mayor que el actual.La propiedad
_UpgradePlatformToolsetFor_<safe_toolset_name>
se define para el conjunto de herramientas actual y su valor no es igual al conjunto de herramientas actual.En estos nombres de propiedad, <safe_toolset_name> representa el nombre del conjunto de herramientas con todos los caracteres no alfanuméricos reemplazados por un carácter de subrayado (_).
Cuando un proyecto se puede actualizar, participa en Solución Retargeting. Para obtener más información, consulte IVsTrackProjectRetargeting2.
Si desea adornar los nombres de proyecto en Explorador de soluciones cuando los proyectos usan un conjunto de herramientas específico, defina una propiedad _PlatformToolsetShortNameFor_<safe_toolset_name>
.
Para obtener ejemplos de definiciones de propiedades de _UpgradePlatformToolsetFor_<safe_toolset_name>
y _PlatformToolsetShortNameFor_<safe_toolset_name>
, consulte el archivo de Microsoft.Cpp.Default.props. Para obtener ejemplos de uso, consulte el archivo $(VCTargetPath)
\Microsoft.Cpp.Platform.targets.
Actualizador de proyecto personalizado
Para usar un objeto de actualizador de proyecto personalizado, implemente un componente MEF, como se muestra aquí:
/// </summary>
[Export("MyProjectUpgrader", typeof(IProjectRetargetHandler))]
[Export(typeof(IProjectRetargetHandler))]
[ExportMetadata("Name", "MyProjectUpgrader")]
[OrderPrecedence(20)]
[PartMetadata(ProjectCapabilities.Requires, ProjectCapabilities.VisualC)]
internal class MyProjectUpgrader: IProjectRetargetHandler
{
// ...
}
El código puede importar y llamar al objeto .vcxproj de actualización predeterminado.
// ...
[Import("VCDefaultProjectUpgrader")]
// ...
IProjectRetargetHandler Lazy<IProjectRetargetHandler>
VCDefaultProjectUpgrader { get; set; }
// ...
IProjectRetargetHandler
se define en Microsoft.VisualStudio.ProjectSystem.VS.dll y es similar a IVsRetargetProjectAsync
.
Defina la propiedad VCProjectUpgraderObjectName
para indicar al sistema de proyecto que use el objeto de actualizador personalizado:
<PropertyGroup>
<VCProjectUpgraderObjectName>MyProjectUpgrader</VCProjectUpgraderObjectName>
</PropertyGroup>
Deshabilitar la actualización del proyecto
Para deshabilitar las actualizaciones del proyecto, use un valor de NoUpgrade
:
<PropertyGroup>
<VCProjectUpgraderObjectName>NoUpgrade</VCProjectUpgraderObjectName>
</PropertyGroup>
Caché y extensibilidad del proyecto
Para mejorar el rendimiento al trabajar con soluciones de C++ de gran tamaño en Visual Studio 2017, se introdujo la caché de proyectos . Se implementa como una base de datos de SQLite rellenada con datos del proyecto y, a continuación, se usa para cargar proyectos sin cargar proyectos de MSBuild o CPS en memoria.
Dado que no hay ningún objeto CPS presente para .vcxproj proyectos cargados desde la memoria caché, no se pueden crear los componentes MEF de la extensión que importan UnconfiguredProject
o ConfiguredProject
. Para admitir la extensibilidad, la memoria caché del proyecto no se usa cuando Visual Studio detecta si un proyecto usa (o es probable que use) extensiones MEF.
Estos tipos de proyecto siempre se cargan completamente y tienen objetos CPS en memoria, por lo que todas las extensiones MEF se crean para ellos:
Proyectos de startups
Los proyectos que tienen un actualizador de proyecto personalizado, es decir, definen una propiedad
VCProjectUpgraderObjectName
Los proyectos que no tienen como destino Windows de escritorio, es decir, definen una propiedad
ApplicationType
Proyectos de elementos compartidos (.vcxitems) y los proyectos que hacen referencia a ellos mediante la importación de proyectos .vcxitems.
Si no se detecta ninguna de estas condiciones, se crea una memoria caché del proyecto. La memoria caché incluye todos los datos del proyecto MSBuild necesarios para responder consultas get
en interfaces VCProjectEngine
. Esto significa que todas las modificaciones en el nivel de archivo de propiedades y destinos de MSBuild realizadas por una extensión solo deben funcionar en proyectos cargados desde la memoria caché.
Envío de la extensión
Para obtener información sobre cómo crear archivos VSIX, vea Envío de extensiones de Visual Studio. Para obtener información sobre cómo agregar archivos a ubicaciones de instalación especiales, por ejemplo, para agregar archivos en $(VCTargetsPath)
, vea Instalación fuera de la carpeta de extensiones.
Recursos adicionales
El sistema de compilación de Microsoft (MSBuild) proporciona el motor de compilación y el formato extensible basado en XML para los archivos de proyecto. Debe estar familiarizado con los conceptos básicos de MSBuild y cómo funciona MSBuild para Visual C++ con el fin de ampliar el sistema de proyectos de Visual C++.
Managed Extensibility Framework (MEF) proporciona las API de extensión que usa CPS y el sistema de proyectos de Visual C++. Para obtener información general sobre cómo CPS usa MEF, consulte CPS y MEF en la información general de VSProjectSystem de MEF.
Puede personalizar el sistema de compilación existente para agregar pasos de compilación o nuevos tipos de archivo. Para obtener más información, consulte MSBuild (Visual C++) Descripción general y Trabajar con las propiedades del proyecto.