1

Traditionally, I used to manually switch between build configurations: debug, full release and lite release. The last one of them not only excludes extra functions, but is also compatible with .NET 3.5 instead of regular .NET 4.5 target. Switching between .NET versions was also accomplished by hand, which resulted in automatic closing and reopening of the project.

As the project has grown bigger, now it is time to split it into parts. Of course, manually switching configurations and platforms for a bunch of projects is not funny, so I edited .proj files and put TargetFrameworkVersion directive into conditional sections, like in many examples here and on other sites.

<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
    <DefineConstants>dotNet=4.5, HaveTesting=True, HaveDumper=True</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'RlzFull' ">
    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
    <DefineConstants>dotNet=4.5, HaveTesting=False, HaveDumper=True</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'RlzLite' ">
    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
    <TargetFrameworkProfile>Client</TargetFrameworkProfile>
    <DefineConstants>dotNet=3.5, HaveTesting=False, HaveDumper=False</DefineConstants>
</PropertyGroup>
<PropertyGroup  Condition=" '$(Configuration)' == 'Debug' ">
    <DebugType>full</DebugType>
    <DebugSymbols>true</DebugSymbols>
    <DefineDebug>true</DefineDebug>
    <DefineTrace>true</DefineTrace>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' != 'Debug' ">
    <DebugType>none</DebugType>
    <DebugSymbols>false</DebugSymbols>
    <DefineDebug>false</DefineDebug>
    <DefineTrace>false</DefineTrace>
</PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'AnyCPU' ">
    <PlatformTarget>AnyCPU</PlatformTarget>
    <Prefer32Bit Condition=" $(TargetFrameworkVersion.Substring(1)) &gt;= 4.5 ">true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'x86' ">
    <PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'x64' ">
    <PlatformTarget>x64</PlatformTarget>
</PropertyGroup>

Apparently, it works with MSBuild launched manually. Accidentally or not, all example authors wrote about manual invocation of build routine. Moreover, some of them added kind of: “You select only a single configuration to use inside Visual Studio”.

However, at least in topic “Conditionally changing target framework version” it is implied that configuration may be changed interactively inside Visual Studio: the GUI will still display the previous .NET version in the project properties window, but the compiler will use correct libraries. But it does not seem to work for me: when another configuration is selected in GUI which requires different .NET version, the previous one (the default one?) is used instead, even after reopening the solution.

The build output log shows that the very first project (LibUtil.dll) is successfully compiled. However, when inspecting the built assembly, it can be seen that it was targeted at .NET 4.x, as it references mscorlib.dll 4.0.0.0 and System.dll 2.0.0.0. When built manually, both referenced libraries are of version 2.0.0.0 for the .NET 3.5 configuration and of version 4.0.0.0 for the .NET 4.5 configuration.

All subsequent projects have a bunch of similar errors in the log:

error BC30002: Type 'FooClass.BarClass' is not defined.
error BC30451: 'FooClass' is not declared. It may be inaccessible due to its protection level.
warning MSB3258: The primary reference "...\LibUtil.dll" could not be resolved because it has an indirect dependency on the .NET Framework assembly "System.Windows.Forms, Version=4.0.0.0, ..." which has a higher version "4.0.0.0" than the version "2.0.0.0" in the current target framework.
warning MSB3268: The primary reference "...\LibUtil.dll" could not be resolved because it has an indirect dependency on the framework assembly "System.Web.ApplicationServices, Version=4.0.0.0, ..." which could not be resolved in the currently targeted framework.

Note the warnings: for a simple library project that actually references System and System.Core only, the log states that it references several dozens of .NET libraries, including those I even never heard of before. :-)

So, the question is: Is it really possible to change the target .NET version along with build configuration inside Visual Studio, or is it only possible when running MSBuild by hand? I expected that the experience should be the same in both CLI and GUI. Without the ability to test different configurations in IDE and track errors easily, Visual Studio is no better than a Notepad with IntelliSense.

Update 1. Apparently, GUI behavior is indeed inconsistent with CLI: when I tried to use hierarchical Choose-When-Otherwise style of conditional project description, the configuration manager in IDE stopped recognizing defined configurations and platforms at all, displaying “Debug” and “Any CPU” (sic) as the only option for each project. Curiously, when trying to add a new configuration or platform with a name already defined in .proj file, IDE confirms that this item exists already.

Update 2. Switching between configurations which target different .NET versions and described in a way that is shown in the listing above, may cause Visual Studio 2012 to crash on each attempt. Unless you want to loose all your breakpoints, etc. by deleting .suo file, it may help to unload all projects except the most simple one and then to switch the configuration — after that other projects may be loaded back safely. Another option is to edit project files and temporarily exclude all TargetPlatformVersion directives that point to a previous version, then switch the solution configuration to a safe value (such as “Debug”), then restore project files.

Community
  • 1
  • 1
Anton Samsonov
  • 1,380
  • 17
  • 34

1 Answers1

1

All issues that I mentioned in the question turned out to be confirmed shortcomings of Visual Studio IDE:

  • Bug 868869 — Switching TargetFrameworkVersion from 4.5 to 3.5 makes compiling from IDE erratic
  • Bug 868917 — IDE ignores project configuration and platform definitions from Choose-When-Otherwise blocks

(The Microsoft guy who responded there have accidentally switched his answers with each other, so don't be confused.) In short, they do admit that such a behavior is not intentional, but they did never intend to achieve identical performance in CLI and IDE — and will not intend to in foreseeable new versions, even though some inconsistencies may result in IDE crash to the point of complete unusability.

Anton Samsonov
  • 1,380
  • 17
  • 34