Giter Site home page Giter Site logo

Comments (3)

sarajoiner avatar sarajoiner commented on May 22, 2024 12

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)' &gt;= '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.

1TheMuffinMan avatar 1TheMuffinMan commented on May 22, 2024

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.

soerennielsen avatar soerennielsen commented on May 22, 2024

oh man, my head hurts. What a mess, but thank you for the explanation.

from msbuild.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.