.vcxproj结构格式说明和.props⽂件⽤法说明(⼀)
1.前⾔
⼀直想写⼀篇关于visual studio项⽬⽂件结构格式和props⽂件⽤法的⽂章,那么开始吧。
C++项⽬⽂件后缀为vcxproj,C#项⽬⽂件后缀为csproj,两者⼤同⼩异,都为xml格式;
项⽬配置⽂件中包含对应项⽬依赖的编译器版本,项⽬环境配置,编译配置、包含⽂件等内容;
官⽅不提倡直接修改项⽬⽂件内容,因为格式结构有很多规则,如果不了解格式结构和规则的话,很容易改出问题;
当然⼀些场景下,直接编辑项⽬⽂件会很便利;
官⽅提倡⽤户配置⾃⼰的.props⽂件,并在项⽬⽂件中import进去即可,这样相当于给了⼀个“官⽅的”编辑⼊⼝,当然.props⽂件也是可以复⽤的,将通⽤的配置写⼊.props⽂件中供多个项⽬使⽤,是不是很便利?好了,有种抽象封装的味道了;
2.项⽬结构
⾸先,看⼀下官⽅对于.vcxproj和.props结构的描述,
下⾯简单总结下⾥⾯的内容,(本来想的简单总结,但是总结的过程中发现虽然有些条⽬官⽅描述讲解的⽐较啰嗦,但是其⽬的是为了让读者更好的理解,所谓苦⼝婆⼼也,写着写着就变成了半总结半⾃主翻译的风格了=-=)
当⽤visual c++创建新项⽬时,会创建.vcxproj⽂件,这是xml格式的;在.vcxproj中可以import进来.props和.targets⽂件;
官⽅建议只⽤IDE来创建和修改.vcxproj⽂件,尽可能⽤visual studio的属性配置页来更改.vcxproj⽂件;
基于MSBuild的项⽬都⽀持包含.props和.targets⽂件,如果你⼀定想⾃⼰编辑项⽬⽂件,那么编辑这个好了;
项⽬⽂件内容和结构上有很多限制,如果⼀定要编辑,要充分熟悉MSBuild并且遵循本⽂(即上⾯官⽅链接中的⽂章,下同)的指导,否则很容易出错;
你懂得,话都说到了这个地步,你不要改啊,很容易出错的,这种格式不是为了⼿动编辑⽽设计的,真的...如果⼀定要改,那么遵循本⽂的指导吧,接下来就是关于项⽬⽂件和相关⽂件结构和基础内容
的说明;
重要!即将开始!
项⽬⽂件的结构必须符合规定的格式,如本⽂所述;
Visual Studio C++项⽬最近不⽀持通配符和直接罗列条⽬项了,⽐如这种不被⽀持了,
<ItemGroup>
<None Include="*.txt"/>
<ClCompile Include="a.cpp;b.cpp"/>
</ItemGroup>
Visual Studio C++项⽬最近在项⽬⽂件路径中不⽀持宏了,⽐如这种不被⽀持了,值得说明的是,这⾥的“不⽀持”是不保证宏在IDE的所有操作中都能如期⼯作,并且在.props⽂件中宏还是被⽀持的;
<ItemGroup>
<ClCompile Include="$(IntDir)\generated.cpp"/>
</ItemGroup>
项⽬⽂件中针对项⽬配置会有多个分开的Group,每个Group的条件必须是如下的形式,
Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"
每条property都应该以正确的标签标注,并放在group⾥,像 描述的那样;
开始了!
⾸先注意项⽬⽂件中顶级元素都有特定的顺序,
1. ⼤部分的property groups和item definition groups出现在import Microsoft.Cpp.Default.props之后(原因如下⽂);
2. 所有的targets在项⽬⽂件的最后import进去;
3. 这⾥有多种property groups,其有着特定的顺序和唯⼀的标签;
项⽬⽂件中元素的顺序是极其重要的,因为MSBuild是基于顺序评估模式的,如果你的项⽬⽂件(包含import进来.props和.targets⽂件)中对于某条property有多处定义,那么最后⼀条定义将重写之前的
定义,即⽣效的是最后⼀条定义,说道这⾥我之前犯过错误,⾃⼰再.props⽂件中定义的⼀个变量值是正确的,但是VS却识别成了其他的值,最后发现是其他的.props⽂件中也有该条变量的定义,也就是“正确的值”被“错误的值”覆盖了;
这是⼀份最⼩的.vcxproj⽂件,其顶级元素也按照规定的顺序排列,
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns='schemas.microsoft/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>
接下来的章节将会介绍这些元素的作⽤,也会解释为什么它们要以这样的顺序排列!
ProjectConfigurations ItemGroup element
<ItemGroup Label="ProjectConfigurations" />
项⽬配置group包含了项⽬配置相关的描述,⽐如Debug|Win32, Release|Win32, Debug|ARM等,⼀些项⽬的设置仅针对特定的项⽬配置,⽐如你将会正确的想设置release环境的编译优化项,⽽此不会针对debug环境;
ProjectConfigurations在编译阶段就不会起作⽤了,也可以将这个元素放到.props⽂件中,这样如果想修改该项的话就不能在编译器中修改了,⽽需要⼿动修改;
ProjectConfiguration elements
项⽬配置包含配置和平台,⽐如release和x64,如下,
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
你可以在Solution Configuration Manager.中管理、编辑项⽬配置;
Globals PropertyGroup element
<PropertyGroup Label="Globals" />
Globals包含项⽬级的设置,⽐如ProjectGuid, RootNamespace, and ApplicationType or ApplicationTypeRevision,后两个经常指的是操作系统,最近⼀个项⽬只能指定⼀种操作系统;
Microsoft.Cpp.default.props Import element
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.default.props" />
Microsoft.Cpp.default.props是不能修改的!它包含了项⽬默认的设置,⽽这些默认设置可能依赖于ApplicationType的不同⽽有不同值;
Configuration PropertyGroup elements
<PropertyGroup Label="Configuration" />
Configuration property group附加有条件(⽐如 Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"),并且每⼀
unicode文件格式
个Configuration中会有多分,这种property group针对特定的Configuration 表⽰了不同的设置. Configuration properties包含了PlatformToolset、系统 property sheets(在Microsoft.Cpp.props中)的包含情况,⽐如, 如果你定义了 这种设
置<CharacterSet>Unicode</CharacterSet>,那么系统 property sheet microsoft.Cpp.unicodesupport.props 将会被包含进来. 如果你查看了Microsoft.Cpp.props的内容,你将会看到:<Import Condition="'$(CharacterSet)' == 'Unicode'"
Project="$(VCTargetsPath)\microsoft.Cpp.unicodesupport.props" />.,这就是上述情况产⽣的原因!
Microsoft.Cpp.props Import element
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
Microsoft.Cpp.props  (直接或通过imports)定义了很多tool-specific properties的默认值,⽐如编译的优化选项、编译的警告等级、MIDL tool's TypeLibraryName property等,并且根据与它紧邻的之前的configuration properties⽽imports多个系统属性表;⽐如下⾯的,其实Microsoft.Cpp.props Import element的该部分功能和Microsoft.Cpp.default.props Import element有相似之处;
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<PlatformToolset>v110</PlatformToolset>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<PlatformToolset>v110</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
ExtensionSettings ImportGroup element
<ImportGroup Label="ExtensionSettings" />
ExtensionSettings组包含作为【⾃定义编译⽣成配置的⼀部分】的属性表的导⼊。⾃定义编译⽣成配置最多由三个⽂件定义:.targets⽂件、.props⽂件和.xml⽂件;这个导⼊组包含.props⽂件的导⼊;
PropertySheets ImportGroup elements
<ImportGroup Label="PropertySheets" />
这个和⽤户通过VS的Property Manager 添加的属性表有关系;
UserMacros PropertyGroup element
<PropertyGroup Label="UserMacros" />
UserMacros包含了你为⾃定义编译过程⽽定义的⼀些变量,⽐如你可以定义变量$(CustomOutputPath)⽤作输出⽬录或者⽤作定义其他变量;这个属性组包含了若⼲条属性;在VS的
项⽬⽂件中这个组是没有内容的,这是因为visual c++不在⽀持宏⽤作配置,但是在属性表(.props)中宏是被⽀持的;想⼀下,如果你不了解此规则的情况下,在项⽬⽂件的UserMacros PropertyGroup中定义了宏,那么会有什么样的⾏为?!
Per-configuration PropertyGroup elements
<PropertyGroup />
这⾥信息量有点⼤...
这⾥有这种property group的多个实例, 对于所有的project configurations,有⼀个configuration;每⼀个property group必须附加有条件;If any configurations are missing, the Project Properties dialog won't work correctly. Unlike the property groups listed before, this one doesn't have a label. 该组包含了项⽬配置级别的设置. These settings apply to all files that are part of the specified item group. Build customization item definition metadata is initialized here.
This PropertyGroup must come after <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> and there must be no other PropertyGroup without a Label before it (otherwise Project Properties editing won't work correctly).由于.props⽂件中经常会定义该组,这也就是为什么⼀般.props⽂件都在<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />之后import的缘由了;
Per-configuration ItemDefinitionGroup elements
<ItemDefinitionGroup />
包含条⽬定义。这些定义必须符合和没有标签的单个配置元素-PropertyGroup相同的条件规则。
ItemGroup elements
<ItemGroup />
ItemGroup包含项⽬中的项(⽐如源⽂件和其他);项⽬中的项不⽀持条件设置(这是因为规则定义将这些项类型处理为了项⽬项);
每⼀个配置的元数据应该包含配置条件,即使它们是⼀样的,⽐如,
<ItemGroup>
<ClCompile Include="stdafx.cpp">
<TreatWarningAsError Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</TreatWarningAsError>
<TreatWarningAsError Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</TreatWarningAsError>
</ClCompile>
</ItemGroup>
Visual Studio C++最近在项⽬项中不再⽀持通配符,
<ItemGroup>
<ClCompile Include="*.cpp"> <!--Error-->
</ItemGroup>
Visual Studio C++最近在项⽬项中也不再⽀持宏,
<ItemGroup>
<ClCompile Include="$(IntDir)\generated.cpp"> <!--not guaranteed to work in all scenarios-->
</ItemGroup>
References被指定在ItemGroup⾥,并且有以下限制,
1. References不⽀持条件配置;
2. References元数据不⽀持条件配置;
Microsoft.Cpp.targets Import element
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
定义(直接或通过imports)C++ targets,像⽣成、清理等。
ExtensionTargets ImportGroup element
<ImportGroup Label="ExtensionTargets" />
这个组包含⾃定义⽣成⽬标⽂件的导⼊。
Impact of incorrect ordering
Visual Studio IDE依赖于项⽬⽂件有事先描述好的顺序,⽐如,当你通过IDE的属性页定义⼀条属性值
得时候,IDE通常会把这条属性定义放在没有标签的属性组⾥⾯。这种顺序保证了⽤户定义的属性值能够重写被系统属性表设置的相应的默认属性值。类似的,⽬标⽂件在项⽬⽂件的结尾处被import进来,这是因为他们⼀来于之前定义的属性,并且通常它们⾃⼰不会定义属性。同样的,⽤户的.props⽂件总是在系统属性表(被Microsoft.Cpp.props包含进来的)之后被import进来,这为了确保⽤户的能够重写被系统属性表设置的默认值。
如果.vcxproj⽂件不遵循这种布局,编译结果可能不会是你所期望的。⽐如,如果你错误的在系统属性表之后import了⽤户定义的属性表,那么⽤户设置的属性值将会被相应的系统属性表中定义的属性值所覆盖。
即使是IDE设计时的经验也在⼀定程度上依赖于元素的正确顺序。⽐如,如果你的.vcxproj⽂件没有包含import属性表的组,IDE⽆法确定要把⽤户通过属性管理器创建的属性表放在哪⾥。这会导致⽤户的属性表被系统的属性表所覆盖。尽管IDE使⽤的启发式⽅法可以容
忍.vcxproj⽂件布局中的轻微不⼀致,我们仍强烈的建议你不要偏离上问中描述的结构。
How the IDE uses element labels
在IDE中,当你在通⽤属性页中设置UseOfAtl属性时,它会被写⼊项⽬⽂件中的Configuration属性组。
同⼀属性页中的⽬标名属性被写⼊每个配置的⽆标签属性组中。Visual Studio会查看属性页的xml⽂件,以获得在何处写⼊每个属性的信息。
Property Sheet layout
下⾯的xml⽚段是⼀个最⼩的.props⽂件布局,它和.vcxproj⽂件很接近,并且.props中的元素的功能可以继承上⽂中描述的那样。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。