使用自定义属性表设置平台工具版本的Visual Studio解析行为

时间:2014-11-14 18:07:14

标签: visual-studio-2010 visual-studio visual-c++ visual-studio-2013 msbuild

我正在将项目从Visual Studio 2010转换为Visual Studio 2013的大型集合(超过600,难以手动管理或通过脚本管理)。

为了使编译器版本(可能还有其他值)尽可能模块化,并在VS2013中使用VS2010编译器构建项目,我在自定义属性表中定义它(称为本机多目标,请参阅{{3 }和MSDN blog)。

我的精简自定义属性表(位于名为my_properties.props的项目文件夹中)看起来像这样

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup Label="Configuration">
        <PlatformToolset>v120</PlatformToolset>
    </PropertyGroup>
</Project>

它在项目的最高位置导入,如Property Manager

中所示

Property Manager

这意味着它将覆盖之前定义的所有设置(虽然这里不相关,但这很难理解)。

现在问题。根据项目中的导入顺序,默认平台工具集是否正确设置为Visual Studio 2013(v120),在这种情况下,它将还原为Visual Studio 2010(v100),不知道在何处定义。

我的精简版项目如下:

<?xml version="1.0" encoding="utf-8"?>
  <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <ItemGroup Label="ProjectConfigurations">
      <ProjectConfiguration Include="Debug|Win32">
        <Configuration>Debug</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|Win32">
      <Configuration>Release</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
  </ItemGroup>
  <PropertyGroup Label="Globals">
    <ProjectGuid>{396A761A-45C9-46AA-BCF0-59FFD306D674}</ProjectGuid>
    <Keyword>Win32Proj</Keyword>
    <RootNamespace>platform_toolset</RootNamespace>
  </PropertyGroup>

  <!-- This is Block A -->
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
  <!-- /A -->

  <!-- This is Block B -->
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <CharacterSet>Unicode</CharacterSet>
  </PropertyGroup>
  <!-- /B -->

  <!-- This is Block C -->
  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
    <Import Project="my_properties.props" />
  </ImportGroup>
  <!-- /C -->

  <!-- This is Block D -->
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <CharacterSet>Unicode</CharacterSet>
  </PropertyGroup>
  <!-- /D -->

  <!-- This is Block E -->
  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
    <Import Project="my_properties.props" />
  </ImportGroup>
  <!-- /E -->

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

通过这个排序A,B,C,D,E,从上到下,我得到一个默认的平台工具集v100 for Debug builds和v120 for release builds,哦,男孩。

将块A移动到最后给出v120 for Release,没有(空字段)用于Debug,因此前面的A看起来很重要(这对于Microsoft的默认/基本其他属性表是有意义的。)

在PropertyGroups前面移动ImportGroups(产生A,C,E,B,D)会导致正确的行为,v120用于Debug和Release,它是&#34;继承&#34; (不是粗体)。

我如何确保项目文件的正确顺序能够安全地集中定义平台工具集? Isnt MSBuild在这里打破基本的XML规则是引入元素的顺序吗?

答案this blog提供了一些重要的提示(&#34; ms警告......命令......&#34;),here线程实际上是在同一方向询问。

即使在不好的情况下,我也可以扩展Makros并拥有以下值,这对我来说似乎很好:

  

$(DefaultPlatformToolset)v120

     

$(PlatfromToolset)v120

     

$(MSBuildToolsVersion)12.0

     

$(VCTargetsPath)... \ V120 \

MSBuild错误?我知道,属性表有点肮脏,如果属性表发生变化,某些值(例如环境变量)似乎被缓存等,你必须重新启动Studio。

非常感谢任何输入!

PS:在Windows 7 64位计算机上使用VS2013 Update 3.

3 个答案:

答案 0 :(得分:1)

平台应该在最开始设置,就像您发布的链接中所描述的那样。它用于Microsoft.Cpp.Default.props / Microsoft.Cpp.props。

你得到的'v100'可能来自其中一个.user文件。你真的需要/拥有它们吗? 我的意思是,在这里:

<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

我的意思是,它们基本上只对特定用户计算机上的自定义构建有用。如果您不使用任何计算机或用户特定的设置,您可以删除它们。这些“用户设置”文件位于用户个人资料文件夹中。

还要注意“Microsoft.Cpp.Default.props”通常在“Microsoft.Cpp.props”之前。

无论如何,面对类似的问题,我最终删除了项目(.vcxproj)文件中的所有内容。然后它似乎工作得很好。干净。在你的情况下,它看起来像这样。

.vcxproj(请注意,没有任何内容与“debug”或“release”或“.user”或其他内容有关。)

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

<PropertyGroup>
  <ConfigurationType>Application</ConfigurationType>
  <ProjectGuid>{49C9EA4B-99DC-47D1-B32E-ACDF297B2A43}</ProjectGuid>
</PropertyGroup>

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

....

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

</Project>

Platform.props(所有.vcxproj文件共享)

<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

<PropertyGroup>
  <PlatformToolset>v120_xp</PlatformToolset>
  <CharacterSet>Unicode</CharacterSet>
</PropertyGroup>

<ItemGroup Label="ProjectConfigurations">
  <ProjectConfiguration Include="Debug|Win32">
    <Configuration>Debug</Configuration>
    <Platform>Win32</Platform>
  </ProjectConfiguration>
  <ProjectConfiguration Include="Release|Win32">
    <Configuration>Release</Configuration>
    <Platform>Win32</Platform>
  </ProjectConfiguration>
</ItemGroup>

答案 1 :(得分:1)

是的,MSBuild文件是XML,但MSBuild处理器本身有多个阶段。以下是Sayed Ibrahim Hashimi和William Bartholomew撰写的精彩内容“Inside the Microsoft Build Engine”的摘录:

  

当MSBuild引擎开始处理构建文件时,它将以自上而下的方式进行评估   以多次通过的方式。这些过程按以下列表顺序描述。

     

0。加载所有环境和全局属性

     
      
  1. 评估属性并导入遇到的处理导入
  2.   
  3. 评估项目定义
  4.   
  5. 评估项目
  6.   
  7. 使用任务评估
  8.   
  9. 开始构建和阅读目标
  10.   

这意味着该属性的最后一个值将获胜(将在最后评估的值)。只有当不存在具有相同名称的属性时,才会仔细编写许多属性以评估此值,例如:

<PropertyGroup>
  <PlatformToolset Condition="$(PlatformToolset)== ''">v10_Toolset</PlatformToolset>
<PropertyGroup>

此方法保证以下内容:此属性在第5阶段之前将具有某些(首次遇到默认)值,但Condition子句允许使用全局属性和环境变量(读取 - 您的构建环境参数)覆盖任何默认值。

因此(如果你想说出属性值应该是什么的“最后一个词”,那么它可能会非常混乱和反直觉) - 你必须将它放在脚本的最后。

另一方面 - 您描述的行为意味着在您包含的脚本中某些内容不符合现有提供的属性(例如,没有此条件子句) - 它可能是您的某个脚本中的错误或故意被覆盖的行为。我建议你找出为什么你的初始值正在改变,否则你会得到非常微妙和棘手的错误。

PS:我也接受MSBuild目标中可能存在错误 - 我发现MSBuild的目标质量略有不同,从“很棒,工作得很好”到“纠结混乱”,所以如果你看到错误的话,不要感到惊讶hacky方法,你需要修复它。

答案 2 :(得分:1)

我发现并在其他帖子中标记了msbuild,PlatformToolset表现得很有趣,VS或命令行也不同。除了确保设置得足够早之外,主要(未包含)文件中可能需要“不自然地”,并且可能在某个特定位置。

使您的模块化包括验证它已经正确。那么至少你可以在一个地方做一个改变,确保你更新每个项目。

即使没有这个很有趣,早期使用 值,因此必须在主力包括之前设置。在IDE中设置的Prop工作表放在底部,这样就无法工作了。