Home Dashboard Directory Help
Search

.NET 2.0~3.5 Compile to .NET 4.0 by Paulo Morgado


Status: 

Closed
 as By Design Help for as By Design


3
1
Sign in
to vote
Type: Bug
ID: 588215
Opened: 8/22/2010 2:01:38 PM
Access Restriction: Public
0
Workaround(s)
view
0
User(s) can reproduce this bug

Description

When ToolsVersion is set to 2.0, no matter what the value set for TargetFrameworkVersion, the compiled binary will be compiled for .NET 4.0
Details
Sign in to post a comment.
Posted by Paulo Morgado on 9/14/2010 at 5:19 PM
I found this bug (that's what it is) on a solution that I had with projects that use MSBee and were being used by developers with Visual Studio 2005 and 2008SP1 (with different solution files, but the same source and project files). That's why all projects had ToolsVersion="2.0".

When upgrading to VS2008SP1/VS2010 (still using MSBee on some projects), I tried to keep ToolsVersion="2.0" (MSBee requires it) and found out that .NET 2.0 projects were being compiled to the 4.0 runtime.

However, the sample was created with Visual Studio 2010 and I just manually edited the value of the ToolsVersion attribute. Visual Studio 2010 never requires an upgrade for this project.

The problem only surfaces inside the IDE. Using devenv.exe from the command line seems to work as I expected.

I would like to thank you for all the detailed information you provided. I learned a few things.

I can understand that this is a corner case and not intended to be supported. My main intention in reporting this bug was for you to be aware of it and, because I’m a developer myself, I know that, sometimes, behind these small innocent leaves hides a huge and terrible forest.

That being said, I can easily accept “win’t fix”. However, although you do not intended Visual Studio to be used as I was using, by your own word, it is not working as designed and, because of that, I cannot accept “by design”. But it’s your issue tracking system, not mine. Maybe you should add a status of "not designed for that".
Posted by Microsoft on 9/14/2010 at 12:22 PM
Paulo,

Let's see if I can help disambiguate the issue of ToolsVersion. We do tend to use this in several ways. :)

ToolsVersion 2.0 is basically MSBuild as it ships in the 2.0 .NET Framework and uses the 2.0 CLR. ToolsVersion 3.5 is same MSBuild.exe (since 3.5 SP1 is an extension of the 2.0 CLR), but with new tasks and targets as supplied in 3.5. ToolsVersion 4.0 is basically the MSBuild as it ships in the 4.0 .NET Framework and usese the 4.0 CLR.

That being said, when we say use 4.0 to build ToolsVersion=2.0, what we really mean is that MSBuild.exe, from the 4.0 .NET Framework is loaded and run (this is all that Visual Studio 2010 can load; and Visual Studio only support ToolsVersion=4.0), but we use the tasks and targets from the 2.0 .NET Framework (which obviously must be installed for this to work). Equivalently, ToolsVersion=3.5 says to run 4.0 with the tasks and targets from the 3.5 .NET Framework.

Visual Studio 2010 does not support round-tripping. What this means is that inside the Visual Studio 2010 IDE, when you load a project that was created with a previous version of Visual Studio and you have not already converted it, you will be prompted to convert the project to Visual Studio 2010. Once you do this, you cannot load the project in previous versions of Visual Studio. One way you can tell if the upgrade has occurred is by looking at the ToolsVersion in the project file. If it is ToolsVersion=4.0, then the project has been upgraded to Visual Studio 2010. There is no support for building with ToolsVersion=2.0 in the Visual Studio 2010 IDE. If you attempt to change the version back to ToolsVersion=2.0, you saw that Visual Studio will attempt to re-upgrade the project. We do not support simultaneous development of a project from different versions of Visual Studio.

However, MSBuild, the build engine underneath Visual Studio, does support backward compatibility. You can only acheive this outside the Visual Studio IDE via the command line. To do this, you can execute MSBuild on the project/solution and use the command line switch "/tv=2.0". This overrides the one in the project file, and tells MSBuild 4.0 to use the 2.0 tasks and targets to build your project. You must make sure that you load the MSBuild from the 4.0 .NET Framework folder for this to work. MSBuild prints the version number by default when being run from the command.

One easy way to make sure you have the "right" one is to use the Visual Studio 2010 Command Prompt shortcut that is supplied in Start menu for Visual Studio 2010. This prompt sets the paths up correctly to make sure you are always using MSBuild.exe from the 4.0 .NET Framework.

Taking the zipped sample that you have supplied (thanks!), I see a couple of issues. First, the solution is Visual Studio 2010, but the project has not been converted. Since, as explained above, different versions are not compatible, this can't work. I see that you have ToolsVersion=2.0 in the project, and that this loads fine. (But it should not. :)) The reason is because 2.0 project don't put ToolsVersion=2.0 in their projects. They don't have ToolsVersion there. As a result, Visual Studio 2010 does not recognize that the project has not been upgraded, and hence does not prompt you to upgrade.

If you remove ToolsVersion from the project, you are prompted to upgrade, and the project works as expected. However, there is a reference in the project to System.Core (a v3.5 Framework assembly). So, technically, you can't target v2.0 and use a v3.5 assembly. In previous versions of Visual Studio, you could get away with this. But, this is only because multi-targeting was not supported. We only had pseudo multi-targeting. We tried to block certain scenarios, but the coverage was not great, so you could easily get away with this. In Visual Studio 2010, you can't get away with this, because multi-targeting knows that if you are targeting 2.0, and you use 3.5 bits, then deploy to a box with only 2.0 on it, it will break at runtime, which is a bad experience. So, you have to additionally have to remove the refernece to 3.5. Doing this, the project builds fine in Visual Studio 2010 using the existing 4.0 tasks and targets. From the command line, you can use this to build using ToolsVersion=2.0:
msbuild VSBugs.sln /tv:2.0

In both of the above, the project builds and reports using the 2.0 CLR.

The basic synopsis is that the fact that you were able to load the project with ToolsVersion=2.0 into Visual Studio 2010 has created a bad experience. We should have disallowed this. And, we don't support round-tripping between versions of Visual Studio. So, you can't develope this application from Visual Studio 2008 and from Visual Stduio 2010. Once you upgrade to Visual Studio 2010, you can only use the project for Visual Studio 2010.

If you want to build for .NET 2.0, or 3.5, or 4.0, that is all fully supported in Visual Studio 2010. But, this means you are using ToolsVersion=4.0 to build these projects in Visual Studio 2010. The backward compatibility for MSBuild is not to allow Visual Studio 2010 to use the .NET 2.0 tools, but instead to allow Visual Studio 2008 to use the new features in MSBuild 4.0 to build their Visual Studio 2008 projects.

Since I have not found any issues here (minus the issue that we allow you to load a project with ToolsVersion=2.0; which we know about and have decided not to fix) and the system is working as designed, I am going to resolve this issue as "By Design".

Thanks for taking the time to produce the sample so that we could understand your scenario fully. I hope the information that I have provided is helpful.

Chuck England
Visual Studio Pro
Program Manager - MSBuild
Posted by Paulo Morgado on 9/6/2010 at 4:38 PM
» If you use ToolsVerison=2.0, then you can't reference or build 4.0. This is no combination to do this. The 2.0 version did not know about 4.0.

In my experience, I can’t avoid it.

» However, we try to be 100% backward compatible. This means that 4.0 can build < 4.0.

Yes it can.

» From looking at what you have, it appears that the 4.0 compiler (so that would be ToolsVersion 4.0) is building against the .NET Framework 2.0. The 4.0 compiler is capable of creating 2.0 CLR (which includes frameworks 2.0, 3.0, and 3.5) and 4.0 CLR assemblies and executables.

» In the project file, the ToolsVersion is stored at the top of the project in the root <Project/> element. (If it is not there, then the default is 2.0.

Removing the ToolsVersion attribute causes Visual Studio 2010 to upgrade the project, which means that Visual Studio 2010 has no default for this.

» The target framework (the one your application is targeted to run against) is stored in the project as the element <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>. This is true for Visual Studio 2010 projects. In previous versions of projects, there were different properties, or no properties used to store target framework. This is because previous versions of the product only support pseudo mutli-targeting.

I know that.

» Let me know when you get the project uploaded, and I can take a look.

I’ve attached a sample.

Have you tried following all the steps to reproduce?

Have you cross checked with Visual Studio 2008?
Posted by Microsoft on 9/6/2010 at 4:06 PM
I don't see any attachments. ???

If you use ToolsVerison=2.0, then you can't reference or build 4.0. This is no combination to do this. The 2.0 version did not know about 4.0.

However, we try to be 100% backward compatible. This means that 4.0 can build < 4.0.

From looking at what you have, it appears that the 4.0 compiler (so that would be ToolsVersion 4.0) is building against the .NET Framework 2.0. The 4.0 compiler is capable of creating 2.0 CLR (which includes frameworks 2.0, 3.0, and 3.5) and 4.0 CLR assemblies and executables.

In the project file, the ToolsVersion is stored at the top of the project in the root <Project/> element. (If it is not there, then the default is 2.0.

The target framework (the one your application is targeted to run against) is stored in the project as the element <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>. This is true for Visual Studio 2010 projects. In previous versions of projects, there were different properties, or no properties used to store target framework. This is because previous versions of the product only support pseudo mutli-targeting.

Let me know when you get the project uploaded, and I can take a look.

Chuck England
Visual Studio Pro
Program Manager - MSBuild
Posted by Paulo Morgado on 9/2/2010 at 5:25 PM
Sorry about that. I've corrected the download.

Going further, "var" is not valid C# 2.0, but the C# 3.0 compiler generates assemblies for the 2.0 runtime the same as the 2.0 compiler. VS2008 uses the 3.5 version and VS2010 uses the 4.0 version.

Changing ToolsVersion to "4.0", changes the output a bit (the 4.0 compiler is used - see below). As far as I remember, the output form Visual Studio is what the command line would be if used but not really the command line compiler.

What setting would force the use of the 4.0 runtime with ToolsVersion="2.0" but not with ToolsVersion="4.0"?

>>>>>

------ Rebuild All started: Project: TargetBug, Configuration: Debug x86 ------
Build started 03-09-2010 01:20:30.
CoreClean:
Deleting file "C:\temp\Projects\VSBugs\TargetBug\bin\Debug\TargetBug.exe".
Deleting file "C:\temp\Projects\VSBugs\TargetBug\bin\Debug\TargetBug.pdb".
Deleting file "C:\temp\Projects\VSBugs\TargetBug\obj\x86\Debug\TargetBug.exe".
Deleting file "C:\temp\Projects\VSBugs\TargetBug\obj\x86\Debug\TargetBug.pdb".
CoreCompile:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Csc.exe /noconfig /nowarn:1701,1702 /nostdlib+ /platform:x86 /errorreport:prompt /warn:4 /define:DEBUG;TRACE /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorlib.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll /debug+ /debug:full /filealign:512 /optimize- /out:obj\x86\Debug\TargetBug.exe /target:exe Program.cs Properties\AssemblyInfo.cs
CopyFilesToOutputDirectory:
Copying file from "obj\x86\Debug\TargetBug.exe" to "bin\Debug\TargetBug.exe".
TargetBug -> C:\temp\Projects\VSBugs\TargetBug\bin\Debug\TargetBug.exe
Copying file from "obj\x86\Debug\TargetBug.pdb" to "bin\Debug\TargetBug.pdb".

Build succeeded.

Time Elapsed 00:00:00.47
========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ==========
Posted by Microsoft on 9/2/2010 at 7:38 AM
Paulo,

The zip file at the referenced site only contains a .sln and no project files.

Can you please update and let me know?

When I created based on the repro steps, the app did not compile, which matches with what you had suspected.

Based on the error log you show above, it looks like something is very wrong. By that I mean with configuration or something. If this project is being built with ToolsVersion=”2.0”, there is no way that v4.0 assemblies could be resolved unless something was really messed up. The 2.0 CLR can’t even load v4.0 types; you would get an invalid assembly exception, or something similar.

Is there any chance that you have set registry or environment values that force the use of the v4.0 CLR?

Chuck England
Visual Studio Pro
Program Manager - MSBuild
Posted by Paulo Morgado on 8/31/2010 at 1:39 PM
Sample solution for anyone who wants to try this:

http://code.msdn.microsoft.com/PauloMorgado/Release/ProjectReleases.aspx?ReleaseId=4905
Posted by Paulo Morgado on 8/31/2010 at 1:18 PM
I know that "var" is not valid C# 2.0. That’s being used precisely for that – it shouldn’t even compile.

Loading the solution after deleting the project’s “bin” and “obj” folders (a rebuild should work just as fine) and setting “MSBuild project build output verbosity” to “Normal”, got this output in the build window of Visual Studio:

>>>>>
------ Build started: Project: TargetBug, Configuration: Debug x86 ------
warning CS1685: The predefined type 'System.Func' is defined in multiple assemblies in the global alias; using definition from 'c:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll'
warning CS1685: The predefined type 'System.Func' is defined in multiple assemblies in the global alias; using definition from 'c:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll'
warning CS1685: The predefined type 'System.Func' is defined in multiple assemblies in the global alias; using definition from 'c:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll'
warning CS1685: The predefined type 'System.Func' is defined in multiple assemblies in the global alias; using definition from 'c:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll'
warning CS1685: The predefined type 'System.Func' is defined in multiple assemblies in the global alias; using definition from 'c:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll'
warning CS1685: The predefined type 'System.Action' is defined in multiple assemblies in the global alias; using definition from 'c:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll'
warning CS1685: The predefined type 'System.Action' is defined in multiple assemblies in the global alias; using definition from 'c:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll'
warning CS1685: The predefined type 'System.Action' is defined in multiple assemblies in the global alias; using definition from 'c:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll'
warning CS1685: The predefined type 'System.Action' is defined in multiple assemblies in the global alias; using definition from 'c:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll'

Compile complete -- 0 errors, 9 warnings
Build started 2010-08-31 21:10:14.
CoreCompile:
C:\Windows\Microsoft.NET\Framework\v2.0.50727\Csc.exe /noconfig /nowarn:1701,1702 /platform:x86 /errorreport:prompt /warn:4 /define:DEBUG;TRACE /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.5\System.Core.dll" /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll /debug+ /debug:full /filealign:512 /optimize- /out:obj\x86\Debug\TargetBug.exe /target:exe Program.cs Properties\AssemblyInfo.cs
CopyFilesToOutputDirectory:
Copying file from "obj\x86\Debug\TargetBug.exe" to "bin\Debug\TargetBug.exe".
copy /y "obj\x86\Debug\TargetBug.exe" "bin\Debug\TargetBug.exe"
TargetBug -> f:\temp\Projects\VSBugs\TargetBug\bin\Debug\TargetBug.exe
Copying file from "obj\x86\Debug\TargetBug.pdb" to "bin\Debug\TargetBug.pdb".
copy /y "obj\x86\Debug\TargetBug.pdb" "bin\Debug\TargetBug.pdb"

Build succeeded.

Time Elapsed 00:00:00.35
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

<<<<<

And this output from the application:

mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Posted by Microsoft on 8/31/2010 at 12:45 PM
Thanks for taking the time to send us this issue.

Note that in the example that you submited, "var" is not valid when build with the "2.0" compiler. When you set the ToolsVersion="2.0", I get an error compiling.

In that situation, since I had already built the v4.0 executable prior to unloading the project from Visual Studio, the v4.0 executable still exists in the bin\Debug folder, which might make you think that we built with 2.0, and created a 4.0 assembly. However, ToolsVersion="2.0" does not know how to create a 4.0 assembly. And, it is only because the build failed, and what I had already built (using ToolsVersion="4.0") was already in the bin\Debug folder.

So, I added "using System.Refelection;" at the top, and changed the "var" to "Assembly". The sample now compiles successfully. When I run it, the output is:
mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

Since this is working fine in Visual Stduio 2010, I am resolving this issue as "No Repro".

Thanks,

Chuck England
Visual Studio Pro
Program Manager - MSBuild
Posted by Microsoft on 8/22/2010 at 5:04 PM
Thank you for your feedback, we are currently reviewing the issue you have submitted. If this issue is urgent, please contact support directly(http://support.microsoft.com)
Sign in to post a workaround.
File Name Submitted By Submitted On File Size  
VSBugs.zip 9/6/2010 2 KB