如何从 MSbuild 设置 PlatformToolset 属性?

How to set PlatformToolset property from MSbuild?

我们experiencing AppVeyor x64 build failures, and trying a suggestion to set PlatformToolset to DefaultPlatformToolset。 属性 值未记录,因此我们要彻底测试它。

我们将 DefaultPlatformToolset 连接到我们的 AppVeyor configuration file:

test_script:

- cmd: >-
    msbuild /t:Build /p:PlatformToolset=DefaultPlatformToolset cryptlib.vcxproj
    msbuild /t:Build /p:PlatformToolset=DefaultPlatformToolset cryptest.vcxproj
    msbuild /t:CopyCryptestToRoot /p:PlatformToolset=DefaultPlatformToolset cryptest.vcxproj
    cryptest.exe v
    cryptest.exe tv all

DefaultPlatformToolset 导致 AppVeyor 失败。这是我们认为一切正确的日志:Build 1.0.129:

msbuild /t:Build /p:PlatformToolset=DefaultPlatformToolset cryptlib.vcxproj
Microsoft (R) Build Engine version 14.0.25420.1
Copyright (C) Microsoft Corporation. All rights reserved.
Build started 8/2/2017 5:14:24 AM.
The target "_ConvertPdbFiles" listed in a BeforeTargets attribute at "C:\Program Files (x86)\MSBuild.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets (45,37)" does not exist in the project, and will be ignored.
The target "_CollectPdbFiles" listed in an AfterTargets attribute at "C:\Program Files (x86)\MSBuild.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets (45,70)" does not exist in the project, and will be ignored.
The target "_CollectMdbFiles" listed in a BeforeTargets attribute at "C:\Program Files (x86)\MSBuild.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets (52,38)" does not exist in the project, and will be ignored.
The target "_CopyMdbFiles" listed in an AfterTargets attribute at "C:\Program Files (x86)\MSBuild.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets (52,71)" does not exist in the project, and will be ignored.
Project "C:\projects\cryptopp\cryptlib.vcxproj" on node 1 (Build target(s)).
C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V140\Microsoft.Cpp.Platform.targets(57,5): error MSB8020: The build tools for DefaultPlatformToolset (Platform Toolset = 'DefaultPlatformToolset') cannot be found. To build using the DefaultPlatformToolset build tools, please install DefaultPlatformToolset build tools.  Alternatively, you may upgrade to the current Visual Studio tools by selecting the Project menu or right-click the solution, and then selecting "Retarget solution". [C:\projects\cryptopp\cryptlib.vcxproj]
Done Building Project "C:\projects\cryptopp\cryptlib.vcxproj" (Build target(s)) -- FAILED.
Build FAILED.

使用MSbuild构建项目时,如何在命令行设置PlatformToolset


None 这些作品。它们会产生与上述类似的错误。

> msbuild /t:Build /p:PlatformToolset=DefaultPlatformToolset cryptlib.vcxproj

> msbuild /t:Build /p:PlatformToolset=$(DefaultPlatformToolset) cryptlib.vcxproj

> msbuild /t:Build /p:PlatformToolset="$(DefaultPlatformToolset)" cryptlib.vcxproj

> msbuild /t:Build /p:PlatformToolset='$(DefaultPlatformToolset)' cryptlib.vcxproj

尝试执行该愚蠢的 MS XML 引用时出现另一个错误:

>msbuild /t:Build /p:PlatformToolset="$(DefaultPlatformToolset)" cryptlib.vcxproj
Microsoft (R) Build Engine version 4.6.1087.0
[Microsoft .NET Framework, version 4.0.30319.42000]
Copyright (C) Microsoft Corporation. All rights reserved.

MSBUILD : error MSB1011: Specify which project or solution file to use because t
his folder contains more than one project or solution file.
'#34' is not recognized as an internal or external command,
operable program or batch file.
'#34' is not recognized as an internal or external command,
operable program or batch file.

然后是这个:

> msbuild /t:Build /p:PlatformToolset=""$(DefaultPlatformToolset)"" cryptlib.vcxproj
Microsoft (R) Build Engine version 4.6.1087.0
[Microsoft .NET Framework, version 4.0.30319.42000]
Copyright (C) Microsoft Corporation. All rights reserved.

Build started 8/2/2017 2:19:15 AM.
Project "c:\Users\Test\cryptlib.vcxproj" on node 1 (Build target(s)).
C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V110\Microsoft.Cpp.Platform.p
rops(15,24): error MSB4115: The "exists" function only accepts a scalar value,
but its argument "$(VCTargetsPath)\Platforms$(Platform)\PlatformToolsets$(Pla
tformToolset)\Microsoft.Cpp.$(Platform).$(PlatformToolset).props" evaluates to
"C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V110\Platforms\x64\Platform
Toolsets\"$(DefaultPlatformToolset)"\Microsoft.Cpp.x64."$(DefaultPl
atformToolset)".props" which is not a scalar value.

关于错误信息的建议...或者右击解决方案,然后选择"Retarget solution",不行。这是远程的,仅限命令行。我们正在尝试弄清楚如何从 How to run VCUpgrade before Appveyor build?

的命令行 运行 VCUpgrade

DefaultPlatformToolset 是一个 MSBuild 属性,它设置在主项目导入的平台 .props 文件之一中。在 C++ 项目文件中的某一点应该有行

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

例如 VS2017 最终依次导入 <msbuild installation>\Microsoft.Cpp\v4.0\V140\Microsoft.Cpp.Default.props,这设置了 属性 使用

<DefaultPlatformToolset>v140</DefaultPlatformToolset>

因为这是一个 msbuild 属性 Appveyor 和 cmd 都不知道它,因此您不能直接从 appveyor.yml 中引用它。即使它是已知的,您也不能使用 $(DefaultPlatformToolset) 来引用它,这是 msbuild 属性 扩展语法,而 cmd 的形式是 %ABC%。你得到的错误都是因为 PlatformToolset 属性 被设置为例如字符串 'DefaultPlatformToolset' 而它需要设置为实际可用平台的名称,例如 v110 或 v140 或 v120_xp 或 ...

如果您想使用 DefaultPlatformToolset,最简单的方法是将其输入到项目文件中。如果需要,它仍然可以从命令行覆盖。替代方案是 运行 msbuild 并让它打印它的值,然后使用 /p:PlatformToolset= 传递它。但这对于 Visual Studio.

中的本地开发构建来说并不是很好

要更改项目文件,请找到定义 PlatformToolset 的部分并将其更改为 $(DefaultPlatformToolset) - 这应该在 [=44= 之后] ] import else 属性 可能尚未定义。为了防止您正在构建的平台由于某种原因未定义 DefaultPlatformToolset(自定义的,或者可能是旧的 VS 版本)首先将其设置为合理的默认值,before Microsoft.Cpp.Default.props。示例:

<PropertyGroup Label="Globals">
  <PlatformToolset>v100</PlatformToolset>
</PropertyGroup>
....
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
....
<PropertyGroup>
  <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
</PropertyGroup>

这是另一种方法:

<!-- Use DefaultPlatformToolset after Microsoft.Cpp.Default.props -->
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<!-- Set DefaultPlatformToolset to v100 (VS2010) if not defined -->
<PropertyGroup Label="EmptyDefaultPlatformToolset">
    <DefaultPlatformToolset Condition=" '$(DefaultPlatformToolset)' == '' ">v100</DefaultPlatformToolset>
  </PropertyGroup>
<PropertyGroup Label="PlatformToolset">
    <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
</PropertyGroup>

确保在导入 Microsoft.Cpp.Default.props 之前设置全局 属性 组元素也很重要。如果未设置它们,则 MSbuild 假定正在构建 Application,并忽略稍后出现的 ConfigurationType

<PropertyGroup Label="Globals">
    <ProjectGuid>{016d3861-ccd6-4a50-83b4-fe4e93bea333}</ProjectGuid>
    <RootNamespace>mylib</RootNamespace>
    <ConfigurationType>StaticLibrary</ConfigurationType>
</PropertyGroup>
...
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
...
<PropertyGroup>
    <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
</PropertyGroup>