有没有简单的方法让 Visual Studio 2015 使用特定的 ToolsVersion?
Is there a simple way to make Visual Studio 2015 use a specific ToolsVersion?
在使用特定版本的 msbuild
构建项目或解决方案时,我可以使用 /toolsversion
或 /tv
开关 select 早期的 .net 工具链:
"C:\Program Files (x86)\MSBuild.0\bin\msbuild" /tv:12.0 amazing.sln
This Just Works for all versions of msbuild
, csc.exe
等版本根据以上内容正确选择:
> "C:\Program Files (x86)\MSBuild.0\bin\msbuild" /tv:4.0 amazing.sln
...
CoreCompile:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Csc.exe ...
...
> "C:\Program Files (x86)\MSBuild.0\bin\msbuild" /tv:12.0 amazing.sln
...
CoreCompile:
C:\Program Files (x86)\MSBuild.0\bin\Csc.exe ...
...
如果我不指定/tv
,那么根据我使用的 msbuild 版本和一些环境变量,我可能会得到任何:
- 在项目文件的顶级元素中指定的 ToolsVersion
- 我使用的
msbuild.exe
版本对应的ToolsVersion
- 来自
msbuild.exe.config
的值
- 来自注册表的值
(参见different versions of the Overriding ToolsVersion Settings page on MSDN)。
因此,为了在构建服务器和我的本地计算机上获得一致的结果,我在 运行 msbuild.exe
时使用 /tv
(实际上,这是在 psake
脚本中强制执行,这也确保它使用相应版本的 msbuild.exe
).
但是 在使用 Visual Studio 构建时我无法使用 /tv
开关。相反,Visual Studio 2013 及更高版本将使用随 Visual Studio 版本附带的 .net 工具链,除非:
- 设置了环境变量
MSBUILDLEGACYDEFAULTTOOLSVERSION
和...
- ...所有项目文件的 ToolsVersion 属性都设置为我要使用的版本。
这太古怪了,我不敢相信有人真的在这么做。因此,我的问题是:
- 有人在做
MSBUILDLEGACYDEFAULTTOOLSVERSION
这件事吗?
- 如果不是,是否有另一种方法可以使 Visual Studio 使用特定的 ToolsVersion 而不是使用随该 ToolsVersion 附带的 Visual Studio 版本?可以存储在版本控制中(因此在项目或其他设置文件中)的东西是理想的。
最后:
- 我应该关心吗?鉴于 C# 编译器的每个后续版本都应该能够处理以前版本的输入,并且我可以在项目文件中设置目标 .net 框架和 C# 语言级别,这是否足以确保可重复构建?
(我的偏见是我应该关心,因为:
- 我希望 IDE 和构建服务器上的构建相同(当然)
- 我希望能够使用 VS2015(和未来版本),因为它 IDE 比以前的版本更好,但在我决定之前我不想被迫使用新的工具链。
也许是我想要的太多...)
有关问题的具体示例,请参阅我在 github 上的 msbuild-vs-vs2015-toolsversion 存储库。
一些背景:我问这个是因为我们最近遇到了一个 CI 构建错误,当时我的一位同事提交了 C# 6.0 代码,该代码在 Visual Studio 2015 的副本上使用 Roslyn 编译得很好,但在 CI 中失败了,因为 that 使用了先前版本的 .net 工具链(他们使用了没有 setter 的自动 属性,这在 Roslyn 中可以,但在早期版本中则不行)。我们将 CI 构建更新到 Roslyn,但我想看看我们是否可以防止这种事情在未来发生。
您在 Visual Studio(工具等)中看到的内容及其背后的代码并不是编译数据中包含的内容,它们只是 visual/readable 表示,当将它们编译为较早版本时您正在制作该版本的可执行文件的 VS 版本。
请记住,如果编译为以前的 .NET 版本,您可能会失去诸如异步功能之类的功能。
注意:您始终可以创建一个 msbuild 文件来构建您的项目,使用它或自行更改您的项目,并且您可以有条件地决定您的工具版本 (https://msdn.microsoft.com/en-us/library/7z253716.aspx) (.csproj也是一个具有不同扩展名的结构化 msbuild 脚本,它也将与 VS 兼容)。
此致...
编辑:
https://msdn.microsoft.com/en-us/library/bb383985.aspx
by setting the $(ProjectToolsVersion)
property on a project within a solution. This lets you build a project in a solution with a Toolset version that differs from that of the other projects.
那么,我想你已经找到答案了 ;)
我通过编写一个 Visual Studio 扩展来解决这个问题,该扩展在构建期间临时设置环境变量 MSBUILDDEFAULTTOOLSVERSION
;要使用的值是从与 .sln
文件位于同一目录中的文件 .toolsversion
中读取的。 psake 脚本读取相同的 .toolsversion
文件并将值传递给 /tv
开关。
可在此处找到扩展代码:https://github.com/guyboltonking/set-toolsversion-extension。可悲的是,我目前没有使用 C++,或者确实没有使用 Visual Studio,所以我无法为它提供任何支持(但我可以告诉你我使用它几个月没有任何问题).
感谢@efaruk 提醒我 MSBUILDDEFAULTTOOLSVERSION
的存在。
编辑:感谢@mbadawi23,现在可以在 VS2015 和 VS2017 中使用该扩展。
要在 Visual Studio 2015 中强制使用特定的 C# 版本,您可以进入项目属性 -> 构建 -> 高级 -> 语言版本。
如果将此设置为 5,编译器将抱怨 C# 6 功能:功能“...”在 C# 5 中不可用。请使用语言版本 6 或更高版本。
此外,ReSharper 也有一些工具。
在使用特定版本的 msbuild
构建项目或解决方案时,我可以使用 /toolsversion
或 /tv
开关 select 早期的 .net 工具链:
"C:\Program Files (x86)\MSBuild.0\bin\msbuild" /tv:12.0 amazing.sln
This Just Works for all versions of msbuild
, csc.exe
等版本根据以上内容正确选择:
> "C:\Program Files (x86)\MSBuild.0\bin\msbuild" /tv:4.0 amazing.sln
...
CoreCompile:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Csc.exe ...
...
> "C:\Program Files (x86)\MSBuild.0\bin\msbuild" /tv:12.0 amazing.sln
...
CoreCompile:
C:\Program Files (x86)\MSBuild.0\bin\Csc.exe ...
...
如果我不指定/tv
,那么根据我使用的 msbuild 版本和一些环境变量,我可能会得到任何:
- 在项目文件的顶级元素中指定的 ToolsVersion
- 我使用的
msbuild.exe
版本对应的ToolsVersion - 来自
msbuild.exe.config
的值
- 来自注册表的值
(参见different versions of the Overriding ToolsVersion Settings page on MSDN)。
因此,为了在构建服务器和我的本地计算机上获得一致的结果,我在 运行 msbuild.exe
时使用 /tv
(实际上,这是在 psake
脚本中强制执行,这也确保它使用相应版本的 msbuild.exe
).
但是 在使用 Visual Studio 构建时我无法使用 /tv
开关。相反,Visual Studio 2013 及更高版本将使用随 Visual Studio 版本附带的 .net 工具链,除非:
- 设置了环境变量
MSBUILDLEGACYDEFAULTTOOLSVERSION
和... - ...所有项目文件的 ToolsVersion 属性都设置为我要使用的版本。
这太古怪了,我不敢相信有人真的在这么做。因此,我的问题是:
- 有人在做
MSBUILDLEGACYDEFAULTTOOLSVERSION
这件事吗? - 如果不是,是否有另一种方法可以使 Visual Studio 使用特定的 ToolsVersion 而不是使用随该 ToolsVersion 附带的 Visual Studio 版本?可以存储在版本控制中(因此在项目或其他设置文件中)的东西是理想的。
最后:
- 我应该关心吗?鉴于 C# 编译器的每个后续版本都应该能够处理以前版本的输入,并且我可以在项目文件中设置目标 .net 框架和 C# 语言级别,这是否足以确保可重复构建?
(我的偏见是我应该关心,因为:
- 我希望 IDE 和构建服务器上的构建相同(当然)
- 我希望能够使用 VS2015(和未来版本),因为它 IDE 比以前的版本更好,但在我决定之前我不想被迫使用新的工具链。
也许是我想要的太多...)
有关问题的具体示例,请参阅我在 github 上的 msbuild-vs-vs2015-toolsversion 存储库。
一些背景:我问这个是因为我们最近遇到了一个 CI 构建错误,当时我的一位同事提交了 C# 6.0 代码,该代码在 Visual Studio 2015 的副本上使用 Roslyn 编译得很好,但在 CI 中失败了,因为 that 使用了先前版本的 .net 工具链(他们使用了没有 setter 的自动 属性,这在 Roslyn 中可以,但在早期版本中则不行)。我们将 CI 构建更新到 Roslyn,但我想看看我们是否可以防止这种事情在未来发生。
您在 Visual Studio(工具等)中看到的内容及其背后的代码并不是编译数据中包含的内容,它们只是 visual/readable 表示,当将它们编译为较早版本时您正在制作该版本的可执行文件的 VS 版本。
请记住,如果编译为以前的 .NET 版本,您可能会失去诸如异步功能之类的功能。
注意:您始终可以创建一个 msbuild 文件来构建您的项目,使用它或自行更改您的项目,并且您可以有条件地决定您的工具版本 (https://msdn.microsoft.com/en-us/library/7z253716.aspx) (.csproj也是一个具有不同扩展名的结构化 msbuild 脚本,它也将与 VS 兼容)。
此致...
编辑:
https://msdn.microsoft.com/en-us/library/bb383985.aspx
by setting the
$(ProjectToolsVersion)
property on a project within a solution. This lets you build a project in a solution with a Toolset version that differs from that of the other projects.
那么,我想你已经找到答案了 ;)
我通过编写一个 Visual Studio 扩展来解决这个问题,该扩展在构建期间临时设置环境变量 MSBUILDDEFAULTTOOLSVERSION
;要使用的值是从与 .sln
文件位于同一目录中的文件 .toolsversion
中读取的。 psake 脚本读取相同的 .toolsversion
文件并将值传递给 /tv
开关。
可在此处找到扩展代码:https://github.com/guyboltonking/set-toolsversion-extension。可悲的是,我目前没有使用 C++,或者确实没有使用 Visual Studio,所以我无法为它提供任何支持(但我可以告诉你我使用它几个月没有任何问题).
感谢@efaruk 提醒我 MSBUILDDEFAULTTOOLSVERSION
的存在。
编辑:感谢@mbadawi23,现在可以在 VS2015 和 VS2017 中使用该扩展。
要在 Visual Studio 2015 中强制使用特定的 C# 版本,您可以进入项目属性 -> 构建 -> 高级 -> 语言版本。
如果将此设置为 5,编译器将抱怨 C# 6 功能:功能“...”在 C# 5 中不可用。请使用语言版本 6 或更高版本。
此外,ReSharper 也有一些工具。