使用MSBuild时强制项目始终使用VS2012 / VC11构建

时间:2016-06-28 11:45:03

标签: visual-studio-2010 visual-studio-2012 msbuild c++-cli

注意:这与众所周知的 VS2010 / VS2012问题有关,在某些情况下,在使用MSBuild构建C ++时必须指定/p:VisualStudioVersion=11.0 / CLI应用程序。

问题:使用引用C ++ / CLI项目文件的MSBuild任务构建VS2012 C ++ / CLI应用程序时,我需要将/p:VisualStudioVersion=11.0添加到MSBuild命令行,否则会出现此错误:

error MSB8008: Specified platform toolset (v110) is not installed or invalid. Please make sure that a supported PlatformToolset value is selected.

仅在安装了VS2010和VS2012的计算机上构建,甚至在Developer Command Prompt for VS2012或自己调用%VS110COMNTOOLS%\vsvars32.bat之后显示。

显然我已经知道了解决方法,但我想摆脱始终指定相同的附加命令行参数的要求。

一些细节:我有一个.proj文件,用于设置用于构建C ++ / CLI应用程序的MSBuild任务。这是它的主要内容(我们称之为Foo.proj):

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

  <ItemGroup>

    <CxxProjects
      Include="$(MSBuildThisFileDirectory)src\**\*.vcxproj"
    />

  </ItemGroup>

  <Target Name="build">
    <MSBuild Projects="@(CxxProjects)
             Properties="VisualStudioVersion=11.0"/>
  </Target>

</Project>

以上内容并不完整,仅供参考。问题是如上所述为MSBuild任务设置属性VisualStudioVersion没有帮助。我仍然得到相同的MSB8008错误。除非......是的,使用MSBuild Foo.proj /p:VisualStudioVersion=11.0

有可能以某种方式解决这个问题 - 我在这里错过了什么吗?如果我只知道如何(我已经尝试过),我甚至可以自己编辑单独的.vcxproj文件。

4 个答案:

答案 0 :(得分:1)

取决于您要修复的级别。

在Microsoft.Cpp.Platform.targets中有一个可以使用的import语句:

<Import Condition="'$(_ToolsetFound)' == 'true' and Exists('$(_PlatformFolder)ImportAfter')" Project="$(_PlatformFolder)ImportAfter\*.targets"/>

从特定于平台的ImportAfter文件夹导入所有* .targets文件。您可以定义在全局级别设置任何属性的最简单文件(对于所有.vcpproj文件)

  

EDIT1   这是此类文件的内容,您可以按照自己想要的方式命名,只需确保它与上面的通配符匹配*.targets.您必须找出文件的正确路径(找出$(_PlatformFolder)中的路径是什么属性

<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" DefaultTargets="build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup><VisualStudioVersion>11.0</VisualStudioVersion></PropertyGroup> </Project>

  

/ EDIT1

或者您可以使用此Microsoft.Cpp.Current.targets导入

<Import Condition=" '$(ForceImportAfterCppTargets)' != '' and exists('$(ForceImportAfterCppTargets)')" Project="$(ForceImportAfterCppTargets)"/> 只需声明$(ForceImportAfterCppTargets)属性,该属性指向一个特定文件,该文件将覆盖每个平台。

  

EDIT2   如果您只想影响构建脚本,这种方法会更好 - 您必须执行相同的操作(将文件放在edit1中)并将路径传递给文件   $(ForceImportAfterCppTargets)财产。您的构建脚本将具有以下内容:

<MSBuild Projects="@(CxxProjects) Properties="ForceImportAfterCppTargets=path_to_my_targets"/>

  

/ EDIT2

或者您可以创建相应的环境变量 - MSBuild emits Properties from Environment variables

希望这有帮助。

PS:如果您可以使用/verbosity:diag生成msbuild日志,这可能对您和我们有很大帮助 - 更容易看到完整且非常详细的日志。两组日志 - 一组具有成功的构建结果,另一组具有失败的日志将有助于实现更多

答案 1 :(得分:1)

VS2012与VS2010组合的具体问题在此处详细说明:Visual Studio project compatibility and VisualStudioVersion

  

如果您从命令行(而不是开发人员)构建Web项目   提示)然后使用的VisualStudioVersion的值将是10.0。那   是我上面展示的属性的人工制品。在这种情况下   您应该将其作为MSBuild属性传递。例如

     

msbuild.exe MyAwesomeWeb.csproj /p:VisualStudioVersion=11.0

     

在此   我明确地传递了这个属性。这将始终覆盖   任何其他机制来确定VisualStudioVersion的值。如果   您正在构建脚本中使用MSBuild任务,然后您可以指定   属性属性中的属性或   AdditionalProperties属性。

该帖子在此处有指向其他帖子的链接:MSBuild: Properties and AdditionalProperties Known Metadata。本文解释了这一点:

  

不同之处在于,如果使用“属性”指定属性   元数据然后使用Properties属性定义的任何属性   MSBuild任务将被忽略。与之相反,如果你使用的话   然后使用AdditionalProperties元数据和两个值   首选项转到AdditionalProperties值。

所以一个解决方案是使用允许在msbuild过程后期定义Properties的AdditionalProperties元数据,如下所示:

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

  <ItemGroup>
    <CxxProjects Include="$(MSBuildThisFileDirectory)src\**\*.vcxproj">
        <AdditionalProperties>VisualStudioVersion=11.0</AdditionalProperties>
    </CxxProjects>
  </ItemGroup>

  <Target Name="build">
    <MSBuild Projects="@(CxxProjects) />
  </Target>

</Project>

答案 2 :(得分:0)

您可以通过将以下标记添加到属性组来指定项目文件中的特定工具集:

<PlatformToolset>v110</PlatformToolset>

你根本不需要任何外部参数。

答案 3 :(得分:0)

所以,这就是。以下是实际最小复制案例 - 我的问题实际上有效。我想我在很多不同的细微变化之间来回切换,我最终发布的内容没有真正测试那些确切的代码。对不起。

罪魁祸首是假设VisualStudioVersion最初没有设置,除非我自己做了 - 至少在构建过程的早期没有。对我而言,MSBuild依赖于Visual Studio,而不仅仅是相反的方式,这是非常不直观的。

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

  <PropertyGroup>
    <!--
      The below causes the problem - VisualStudioVersion already
      have a 'default' value of 10.0 at this point and therefore
      is never set to 11.0
    -->
    <VisualStudioVersion Condition="'$(VisualStudioVersion)' != ''">11.0</VisualStudioVersion>
  </PropertyGroup>

  <ItemGroup>

    <CxxProjects
      Include="$(MSBuildThisFileDirectory)src\**\*.vcxproj"
    />

  </ItemGroup>

  <Target Name="build">
    <MSBuild Projects="@(CxxProjects)
             Properties="VisualStudioVersion=$(VisualStudioVersion)"/>
  </Target>

</Project>

从来没有对我有用的是直接在.vcxproj文件中设置VisualStudioVersionPlatformToolset(是的,无条件的) - 这在构建过程中似乎为时已晚,至少在以这种特殊方式建造时。

让我感到困惑的另一件事是,即使显式为VS2012设置构建环境,VisualStudioVersion属性也默认为VS2010。

感谢那些回复的人。实际上让我发现问题的是对我使用<AdditionalProperties>的原始问题的评论。我尝试了这个并且'意外'硬编码11.0而不是使用$(VisualStudioVersion) - 这导致我通过无条件设置VisualStudioVersion来使其适用于其他情况:

<PropertyGroup>
  <VisualStudioVersion>11.0</VisualStudioVersion>
</PropertyGroup>

因此,如果他将他的建议作为回复而不是评论发布,我将奖励给该评论者。否则我只会让自动奖励发生。