Comments (3)
This is "by design" because you're using the .NET 4.X version of the MSBuild engine, which does not officially support VS 2013+ projects. Per the comment in Microsoft.Common.props above the line you flagged:
<PropertyGroup Condition="'$(MSBuildAssemblyVersion)' == '' and ('$(VisualStudioVersion)' != '' and '$(VisualStudioVersion)' >= '12.0')">
<!--
Reset VisualStudioVersion if it's 12.0+: Should be 10.0 if VS 2010 is installed or 11.0
otherwise, but since we don't have a good way of telling whether VS 2010 is installed,
make it 11.0 if VS 2012 is installed or 10.0 otherwise. The reset should be safe
because if it was already set to something (e.g. 11.0 in a VS 2012 command prompt)
then MSBuild's internal VisualStudioVersion-defaulting code should never come into
the picture, so the only way it could be 12.0+ when building a TV 12.0 project
(because we're in this file) using MSBuild 4.5 (because MSBuildAssemblyVersion
hasn't been set) is if it's a TV 12.0 project on an empty command prompt.
-->
If you update your tool to instead use the VS 2013 or VS 2015 (or OSS :) ) version of MSBuild, you should no longer see the behavior difference caused by the common props. (Although as explained below, you will also default to always using the "current" ToolsVersion instead of reading it from the project file.)
Historical background for the curious:
In VS 2013, we updated ToolsVersion for the first time since Visual Studio started making asset compatibility guarantees (VS 2010 SP1). At that point, we had to figure out what it meant for, e.g., MSBuild N to build a compatible project from VS N+1, and the above code is part of the answer we came to. Specifically, the answer to the question of "what happens when VS 2012 (MSBuild 4.X) attempts to build a VS 2013 (MSBuild 12) project?".
Until VS 2013, we'd simply read the "ToolsVersion" tag in the project and used it. That worked in the world pre-VS 2010 SP1, where Visual Studio forced an update to the ToolsVersion every release and only supported loading projects with that ToolsVersion -- if something was ToolsVersion 3.5, you could depend on the fact that it only worked with, and was only expected to work with, VS 2008. And if someone tried to build a ToolsVersion 3.5 project on a machine without VS 2008 / .NET 3.5 installed ... well, that was their problem.
(Side note: we're speaking specifically of build process components, not the core engine, here. All later versions should be capable of building projects from all earlier versions of MSBuild, with the appropriate build process, as long as that build process is installed.)
It also worked in the world of VS 2010 SP1 / VS 2012, because due to MSBuild being an in-place update from 4.0 -> 4.5, the ToolsVersion didn't change -- all tool differentiation was done at the sub-toolset level (as directed by VisualStudioVersion).
However, in VS 2013, with ToolsVersion 12.0, and with the expectation that the following release would update ToolsVersion yet again, we had to answer the question, "What is the appropriate behavior for a ToolsVersion 14.0 project loaded in VS 2013?"
We couldn't just say "Use the 14.0 build process", because (a) there's no guarantee that VS 2015 would even be on the machine, (b) since VS 2013 is built against MSBuild 12, if there was any new MSBuild syntax introduced in VS 2015, there was a non-trivial chance that MSBuild 12 wouldn't even be able load or build the project, and (c) even if MSBuild could, if there were sufficiently large functional differences in the build process for a particular project type between VS 2013 and 2015, all the VS support infrastructure (project systems, designers, etc.) might behave in strange/unexpected ways.
So the answer we came to was that we'd make MSBuild ignore the "ToolsVersion" tag in project file by default, and always use the "current" ToolsVersion. Thus, in the above example, even though the project file said 'ToolsVersion="14.0"', VS 2013 (MSBuild 12) would build the project as though it were a ToolsVersion="12.0" project. All tools would be known to exist, all behavior would be as expected.
Cool. That solved VS 2013 and all future versions of VS.
However, the asset compatibility guarantee wasn't just "VS 2013 and up", it included VS 2010 SP1 and VS 2012, which were based on MSBuild 4.0 and 4.5 respectively.
In MSBuild 4.0, we'd added some much simpler defaulting logic: If MSBuild didn't recognize the ToolsVersion in the project file, it would default to the current version ("4.0"). So as long as someone loaded a 12.0 or higher project on a machine with ONLY VS 2010 and/or VS 2012 installed, we were also fine.
But if someone, say, attempted to load a ToolsVersion 12.0 project in VS 2010 SP1 on a machine with both that and VS 2013 installed, MSBuild 4.X (probably technically 4.5.1 since that's what comes with 2013) would happily load the project up as a ToolsVersion 12.0 project ... right until the point where it ran into a construct it didn't recognize, at which point it would log some likely-unhelpful error and exit.
We couldn't do anything about the fact that MSBuild 4.X would attempt to load the project as a ToolsVersion 12.0 project. (At least not without changing MSBuild 4.X, which would have been ... logistically difficult.) What we could do, however, was make that ToolsVersion 12.0 project "look like" a ToolsVersion 4.X project as much as possible. To do this, we added a new built-in property, MSBuildAssemblyVersion, that we could then key off of in the targets: if it existed, we were 12+, business as usual. If it didn't exist, we were 4.X trying to build a 12+ project, and tweaking was required.
Thus the above code in Microsoft.Common.props, to reset VisualStudioVersion to one of the allowed 4.X values: 10.0 or 11.0.
Thus also the redirection code e.g. here: https://github.com/Microsoft/msbuild/blob/master/src/XMakeTasks/Microsoft.Common.targets#L32 to make sure that, when a project imported "$(MSBuildToolsPath)\Microsoft.Common.targets", it would get the 4.X one, instead of the 12+ one.
This wasn't a 100% complete solution:
- ToolsVersion still reported the original value
- If the project file itself made use of MSBuild 12+ constructs, there was nothing we could do to keep MSBuild 4.X from breaking. (Though in that case, the authors of that project type ought to have made sure their project templates set a MinimumVisualStudioVersion of 12+, so that the IDE's "this project is not compatible" logic would take over.)
But we found that in practice, most of the time it was "good enough".
from msbuild.
Since the VisualStudioVersion resolves to 10 instead of 14 when I create an asp.net core project with the web api template the build is looking for VisualStudio\v10.0\DotNet\Microsoft.DotNet.Props
, but that file lives under the v14.0 folder.
from msbuild.
oh man, my head hurts. What a mess, but thank you for the explanation.
from msbuild.
Related Issues (20)
- Item operation perf in _GetCopyToOutputDirectoryItemsFromTransitiveProjectReferences HOT 3
- [Bug]: Inconsistent floating point behaviour changed between msbuild 16 and 17 HOT 2
- Item to copy to output
- ProjectEvaluationFinished event is not sent if there was an error during evaluation
- [Bug]: TaskItem normalises path to build platform, not target platform HOT 7
- Configuration - ConfigurationContext should contain infra config as well
- [Bug]: Escape , and ;= doesn't work for global property when build with dotnet, but html encode %3C and %3B= works well HOT 1
- [Bug]: CustomAnalyzerTest tests fail on macOS 13 and 14
- nuget restore fails bcs Microsoft.CSharp.Core.targets was not found. HOT 2
- [BuildCheck] Add BuildCheck run notifications to msbuild output
- [BuildCheck] Document in public feature documentation that the user should not add untrusted build analyzers.
- [BuildCheck] Document vulnerabilities in 3rd party checks are not the responsibility of msbuild HOT 1
- [Feature Request]: Optimise dependencies to reduce dependency graph HOT 2
- [Bug]: Could not load file or assembly 'Microsoft.Build, Version=15.1.0.0'. The specified file cannot be found
- Document common hook points for build extensions HOT 1
- Add BuildRequestStarted event HOT 1
- Document the binlog update necessary steps
- [Bug]: The calculated values in windows and linux environments are inconsistent HOT 7
- [Bug]: Inconsistent behavior when using Choose element for conditional package references in MSBuild HOT 1
- [Feature Request]: Diagnostic log "Environment at start of build" should record whether long paths enabled HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from msbuild.