Estructura de los archivos .vcxproj
y .props
MSBuild es el sistema de proyectos predeterminado de Visual Studio; cuando se elige Archivo>Nuevo proyecto en Visual C++ se crea un proyecto de MSBuild cuya configuración se almacena en un archivo de proyecto XML que tiene la extensión .vcxproj
. El archivo de proyecto también puede importar archivos .props
y .targets
en los que se puede almacenar la configuración.
Si tiene previsto mantener las propiedades del proyecto en el IDE, se recomienda crear y modificar .vcxproj
los proyectos en el IDE y evitar modificaciones manuales en los archivos. En la mayoría de los casos, nunca es necesario editar manualmente el archivo del proyecto. Las modificaciones manuales pueden interrumpir las conexiones del proyecto necesarias para modificar la configuración del proyecto en las páginas de propiedades de Visual Studio y pueden provocar errores de compilación difíciles de depurar y reparar. Para obtener más información sobre el uso de las páginas de propiedades, vea Establecimiento del compilador de C++ y propiedades de compilación en Visual Studio.
A escala, administrar muchos proyectos individuales en el IDE se vuelve tedioso y propenso a errores. Es difícil mantener la coherencia o aplicar la estandarización en decenas o cientos de proyectos. En estos casos, vale la pena editar los archivos del proyecto para usar archivos personalizados .props
o .targets
para propiedades comunes en muchos proyectos. También puede usar estos archivos cuando necesite personalizaciones que no sean posibles en el IDE. Lugares útiles para insertar personalizaciones son los archivos Directory.Build.props
y Directory.Build.targets
, que se importan automáticamente en todos los proyectos basados en MSBuild.
En algunos casos, es posible que los archivos personalizados .props
o .targets
solos no sean suficientes para sus necesidades de administración de proyectos. Es posible que tenga que modificar .vcxproj
manualmente archivos de proyecto o hojas de propiedades. La edición manual requiere una buena comprensión de MSBuild y debe seguir las instrucciones de este artículo. Para que el IDE cargue y actualice los archivos .vcxproj
automáticamente, estos archivos tienen varias restricciones que no se aplican a otros archivos de proyecto de MSBuild. Los errores pueden hacer que el IDE se bloquee o se comporte de maneras inesperadas.
En el caso de escenarios de edición manual, este artículo contiene información básica sobre la estructura de .vcxproj
y los archivos relacionados.
Consideraciones importantes
Si decide editar manualmente un archivo .vcxproj
, tenga en cuenta estos hechos:
La estructura del archivo debe seguir un formato establecido, que se describe en este artículo.
En la actualidad, el sistema de proyectos de C++ en Visual Studio no admite caracteres comodín ni listas en los elementos de proyecto. Por ejemplo, estos formatos no se admiten:
<ItemGroup> <None Include="*.txt"/> <ClCompile Include="a.cpp;b.cpp"/> </ItemGroup>
Para más información sobre la compatibilidad con caracteres comodín en proyectos y posibles soluciones, consulte
.vcxproj
Archivos y caracteres comodín.En la actualidad, el sistema de proyectos de C++ en Visual Studio no admite macros en las rutas de acceso de los elementos de proyecto. Por ejemplo, este formato no se admite:
<ItemGroup> <ClCompile Include="$(IntDir)\generated.cpp"/> </ItemGroup>
"Incompatible" significa que no se garantiza que las macros funcionen en todas las operaciones del IDE. Las macros que no cambian su valor en distintas configuraciones deberían funcionar, pero podrían no conservarse si un elemento se mueve a otro proyecto o filtro. Las macros que cambian su valor en diferentes configuraciones causarán problemas. El IDE no espera que las rutas de acceso del elemento de proyecto sean diferentes para distintas configuraciones de proyecto.
Para agregar, quitar o modificar correctamente las propiedades del proyecto al editarlas en el cuadro de diálogo Propiedades del proyecto, el archivo debe contener grupos distintos para cada configuración del proyecto. Las condiciones deben tener este formato:
Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"
Cada propiedad se debe especificar en el grupo con la etiqueta correcta, como se indica en el archivo de regla de la propiedad. Para obtener más información, vea Archivos de regla XML de página de propiedades.
Elementos de archivo .vcxproj
Puede inspeccionar el contenido de un archivo .vcxproj
mediante cualquier editor XML o de texto. Puede verlo en Visual Studio si hace clic con el botón derecho en el proyecto en el Explorador de soluciones, selecciona Descargar proyecto y después Editar Foo.vcxproj.
Lo primero que debe tener en cuenta es que los elementos de nivel superior aparecen en un orden concreto. Por ejemplo:
La mayoría de los grupos de propiedades y grupos de definición de elemento aparecen después de la importación de Microsoft.Cpp.Default.props.
Todos los destinos se importan al final del archivo.
Hay varios grupos de propiedad, cada uno con una etiqueta única, y aparecen en un orden concreto.
El orden de los elementos en el archivo de proyecto es muy importante, porque MSBuild se basa en un modelo de evaluación secuencial. Si el archivo de proyecto, incluidos todos los archivos .props
y .targets
importados, consta de varias definiciones de una propiedad, la última definición invalida las anteriores. En el ejemplo siguiente, se establecerá el valor "xyz" durante la compilación porque el motor de MSBUild lo encuentra en último lugar durante su evaluación.
<MyProperty>abc</MyProperty>
<MyProperty>xyz</MyProperty>
En el fragmento de código siguiente se muestra un archivo .vcxproj
mínimo. Cualquier archivo .vcxproj
generado por Visual Studio contendrá estos elementos de MSBuild de nivel superior. Y, aparecerán en este orden, aunque pueden contener varias copias de cada elemento de nivel superior. Los atributos Label
son etiquetas arbitrarias que solo se usan en Visual Studio como indicadores para la edición; no tienen ninguna otra función.
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
<ItemGroup Label="ProjectConfigurations" />
<PropertyGroup Label="Globals" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.default.props" />
<PropertyGroup Label="Configuration" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings" />
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup />
<ItemGroup />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets" />
</Project>
En las secciones siguientes se describe el propósito de cada uno de estos elementos y por qué se ordenan de esta forma:
Elemento de proyecto
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns='http://schemas.microsoft.com/developer/msbuild/2003' >
Project
es el nodo raíz. Especifica la versión de MSBuild que se va a usar y también el destino predeterminado que se va a ejecutar cuando este archivo se pasa a MSBuild.exe.
Elemento ItemGroup ProjectConfigurations
<ItemGroup Label="ProjectConfigurations" />
ProjectConfigurations
contiene la descripción de la configuración del proyecto. Algunos ejemplos son Debug|Win32, Release|Win32, Debug|ARM y así sucesivamente. Muchas configuraciones de proyecto son específicas de una configuración determinada. Por ejemplo, es probable que le interese establecer propiedades de optimización para una compilación de versión pero no para una compilación de depuración.
El grupo de elementos ProjectConfigurations
no se usa en tiempo de compilación. El IDE de Visual Studio lo necesita para poder cargar el proyecto. Este grupo de elementos se puede mover a un archivo .props
e importar al archivo .vcxproj
. Sin embargo, en ese caso, si necesita agregar o quitar configuraciones, debe editar manualmente el archivo .props
; no se puede usar el IDE.
Elementos ProjectConfiguration
En el fragmento de código siguiente se muestra una configuración de proyecto. En este ejemplo, "Debug|x64" es el nombre de la configuración. El nombre de la configuración de proyecto debe estar en el formato $(Configuration)|$(Platform)
. Un nodo ProjectConfiguration
pude tener dos propiedades: Configuration
y Platform
. Estas propiedades se establecerán de manera automática con los valores especificados aquí cuando la configuración está activa.
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
El IDE espera encontrar una configuración de proyecto para cualquier combinación de valores Configuration
y Platform
usados en todos los elementos ProjectConfiguration
. A menudo, esto significa que es posible que un proyecto tenga configuraciones sin sentido para satisfacer este requisito. Por ejemplo, si un proyecto tiene estas configuraciones:
Debug|Win32
Retail|Win32
Optimización de 32 bits especial|Win32
también debe tener estas configuraciones, aunque "Optimización de 32 bits especial" no tenga sentido para x64:
Depuración|x64
Retail|x64
Optimización de 32 bits especial|x64
Puede deshabilitar los comandos de compilación e implementación para cualquier configuración en el Administrador de configuración de soluciones.
Elemento PropertyGroup Globals
<PropertyGroup Label="Globals" />
Globals
contiene valores de nivel de proyecto, como ProjectGuid
, RootNamespace
y ApplicationType
o ApplicationTypeRevision
. Las dos últimas suelen definir el sistema operativo de destino. Un proyecto solo puede tener como destino un único sistema operativo porque, actualmente, las referencias y los elementos de proyecto no pueden tener condiciones. Normalmente estas propiedades no se reemplazan en otros lugares del archivo de proyecto. Este grupo no depende de la configuración y, por tanto, normalmente solo hay un grupo Globals
en el archivo de proyecto.
Elemento de importación Microsoft.Cpp.default.props
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.default.props" />
La hoja de propiedades Microsoft.Cpp.default.props se incluye con Visual Studio y no se puede modificar. Contiene la configuración predeterminada para el proyecto. Es posible que los valores predeterminados varíen según el valor de ApplicationType.
Elementos de configuración PropertyGroup
<PropertyGroup Label="Configuration" />
Un grupo de propiedades Configuration
tiene una condición de configuración adjunta (como Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"
) y hay varias copias, una por cada configuración. Este grupo de propiedades hospeda las propiedades que se establecen para una configuración concreta. Las propiedades de configuración incluyen PlatformToolset y también controlan la inclusión de hojas de propiedades del sistema en Microsoft.Cpp.props. Por ejemplo, si se define la propiedad <CharacterSet>Unicode</CharacterSet>
, se incluirá la hoja de propiedades del sistema microsoft.Cpp.unicodesupport.props. Si examina Microsoft.Cpp.props, verá la línea: <Import Condition="'$(CharacterSet)' == 'Unicode'" Project="$(VCTargetsPath)\microsoft.Cpp.unicodesupport.props" />
.
Elemento de importación Microsoft.Cpp.props
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
En la hoja de propiedades Microsoft.Cpp.props (directamente o a través de las importaciones) se definen los valores predeterminados para muchas propiedades específicas de la herramienta. Entre los ejemplos se incluyen las propiedades Optimization y Warning Level del compilador, la propiedad TypeLibraryName de la herramienta MIDL, etc. También importa varias hojas de propiedades del sistema en función de las propiedades de configuración que se definan en el grupo de propiedades inmediatamente anterior.
Elemento ImportGroup ExtensionSettings
<ImportGroup Label="ExtensionSettings" />
El grupo ExtensionSettings
contiene las importaciones para las hojas de propiedades que forman parte de las personalizaciones de compilación. Una personalización de compilación se define por hasta tres archivos: un archivo .targets
, un archivo .props
y un archivo .xml
. Este grupo de importación contiene las importaciones del archivo .props
.
Elementos ImportGroup PropertySheets
<ImportGroup Label="PropertySheets" />
El grupo PropertySheets
contiene las importaciones de hojas de propiedades de usuario. Estas importaciones son las hojas de propiedades que se agregan mediante la vista Administrador de propiedades de Visual Studio. El orden en que se muestran estas importaciones es importante y se refleja en el Administrador de propiedades. El archivo de proyecto normalmente contiene varias instancias de este tipo de grupo de importación, una para cada configuración de proyecto.
Elemento PropertyGroup UserMacros
<PropertyGroup Label="UserMacros" />
UserMacros
contiene propiedades que se crean como variables que se usan para personalizar el proceso de compilación. Por ejemplo, se puede definir una macro de usuario para definir la ruta de acceso de salida personalizada como $(CustomOutputPath) y usarla para definir otras variables. Este grupo de propiedades contiene este tipo de propiedades. En Visual Studio, este grupo no se rellena en el archivo de proyecto porque Visual C++ no admite macros de usuario para configuraciones. Las macros de usuario se admiten en las hojas de propiedades.
Elementos PropertyGroup por cada configuración
<PropertyGroup />
Hay varias instancias de este grupo de propiedades, una por cada configuración para todas las configuraciones de proyecto. Cada grupo de propiedades debe tener una condición de configuración adjunta. Si falta alguna configuración, el cuadro de diálogo Propiedades del proyecto no funcionará correctamente. A diferencia de los grupos de propiedades enumerados antes, este no tiene una etiqueta. Este grupo contiene la configuración de nivel de configuración del proyecto. Esta configuración se aplica a todos los archivos que forman parte del grupo de elementos especificado. Los metadatos de definición del elemento de personalización de compilación se inicializan aquí.
Este grupo de propiedades debe aparecer después de <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
y no debe haber ningún otro sin una etiqueta delante (en caso contrario, la edición de las propiedades del proyecto no funcionará correctamente).
Elementos ItemDefinitionGroup por cada configuración
<ItemDefinitionGroup />
Contiene definiciones de elementos. Estas definiciones deben seguir las mismas reglas de condiciones que los elementos PropertyGroup
sin etiqueta en cada configuración.
Elementos ItemGroup
<ItemGroup />
Los elementos ItemGroup
contienen los elementos (archivos de origen, etc.) del proyecto. No se admiten condiciones para los elementos de proyecto (es decir, tipos de elemento que se tratan como elementos de proyecto mediante definiciones de reglas).
Los metadatos deben tener condiciones de configuración para cada configuración, incluso si son las mismas. Por ejemplo:
<ItemGroup>
<ClCompile Include="stdafx.cpp">
<TreatWarningAsError Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</TreatWarningAsError>
<TreatWarningAsError Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</TreatWarningAsError>
</ClCompile>
</ItemGroup>
En la actualidad, el sistema de proyectos de C++ en Visual Studio no admite caracteres comodín en los elementos de proyecto.
<ItemGroup>
<ClCompile Include="*.cpp"> <!--Error-->
</ItemGroup>
En la actualidad, el sistema de proyectos de C++ en Visual Studio no admite macros en los elementos de proyecto.
<ItemGroup>
<ClCompile Include="$(IntDir)\generated.cpp"> <!--not guaranteed to work in all scenarios-->
</ItemGroup>
Las referencias se especifican en un ItemGroup y tienen estas limitaciones:
Las referencias no admiten condiciones.
Las metadatos de referencias no admiten condiciones.
Elemento de importación Microsoft.Cpp.targets
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
Define (directamente o a través de importaciones) destinos de C++ como compilación, limpieza, etc.
Elemento ImportGroup ExtensionTargets
<ImportGroup Label="ExtensionTargets" />
Este grupo contiene las importaciones para los archivos de destino de personalización de compilación.
Consecuencias de la ordenación incorrecta
El IDE de Visual Studio depende de que el archivo de proyecto tenga la ordenación descrita anteriormente. Por ejemplo, cuando se define un valor de propiedad en las páginas de propiedades, el IDE normalmente colocará la definición de propiedad en el grupo de propiedades con la etiqueta vacía. Esta ordenación garantiza que los valores predeterminados de las hojas de propiedades del sistema se reemplazan por valores definidos por el usuario. De igual forma, los archivos de destino se importan al final, ya que consumen las propiedades definidas anteriormente y porque generalmente no definen propiedades propias. Del mismo modo, las hojas de propiedades de usuario se importan después de las hojas de propiedades del sistema (incluidas por Microsoft.Cpp.props
). Este orden garantiza que el usuario pueda invalidar los valores predeterminados incluidos en las hojas de propiedades del sistema.
Si un archivo .vcxproj
no sigue este diseño, es posible que los resultados de la compilación no sean los esperados. Por ejemplo, si importa una hoja de propiedades del sistema por error después de las hojas de propiedades definidas por el usuario, la configuración del usuario se reemplazará por las hojas de propiedades del sistema.
Incluso la experiencia en tiempo de diseño del IDE depende hasta cierto punto del orden correcto de los elementos. Por ejemplo, si el archivo .vcxproj
no tiene el grupo de importación PropertySheets
, es posible que el IDE no pueda determinar dónde se debe colocar una hoja de propiedades nueva que el usuario ha creado en el Administrador de propiedades. Como resultado, una hoja del sistema podría reemplazar una hoja del usuario. Aunque la heurística que usa el IDE puede tolerar incoherencias poco importantes en el diseño del archivo .vcxproj
, se recomienda encarecidamente no desviarse de la estructura mostrada anteriormente en este artículo.
Cómo usa el IDE las etiquetas de elemento
En el IDE, al establecer la propiedad UseOfAtl en la página de propiedades general, se escribe en el grupo de propiedades de configuración del archivo de proyecto. La propiedad TargetName de la misma página de propiedades se escribe en el grupo de propiedades sin etiqueta en cada configuración. Visual Studio busca en el archivo .xml de la página de propiedades la información sobre dónde se escribe cada propiedad. Para la página de propiedades General, suponiendo que tenga una versión en inglés de Visual Studio 2019 Enterprise Edition, ese archivo es %ProgramFiles(x86)%\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\VC\VCTargets\1033\general.xml
. En el archivo de reglas XML de página de propiedades se define la información estática sobre una regla y todas sus propiedades. Parte de esta información es la posición preferida de una propiedad de regla en el archivo de destino (es decir, el archivo donde se escribirá su valor). La posición preferida se especifica mediante el atributo Label de los elementos de archivo de proyecto.
Diseño de la hoja de propiedades
El fragmento de código XML siguiente es un diseño mínimo de un archivo de hoja de propiedades (.props). Es similar a un archivo .vcxproj
, y la funcionalidad de los elementos .props
se puede deducir de la explicación anterior.
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup />
<ItemGroup />
</Project>
Para crear una hoja de propiedades propia, copie uno de los archivos .props
de la carpeta VCTargets
y modifíquelo para sus fines. En Visual Studio 2019 Enterprise Edition, la ruta de acceso predeterminada de VCTargets
es %ProgramFiles%\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\VC\VCTargets
.
Consulte también
Establecimiento del compilador de C++ y de propiedades de compilación en Visual Studio
Archivos XML de página de propiedades
Archivos .vcxproj
y comodines