Splitting Large Solutions

Note: I am a Microsoft Employee, but my views are my own. (*whew* got that off my chest, and satisfied internal requirements)

If you have a large solution, you may find that yourself wanting to split your solution into several parts. If your projects are not inter-connected, this works fine. Basically, you just move the various apps into their own solutions. This allows you to load them faster in the Visual Studio.

But, sometimes you just have lots of interrelated projects. If you simply make two copies of the solution and remove half of the projects from one solution, and half from the other, then some of the projects you need when you build will not be in the solution. And, as a result, you will have no Solution Configuration information to tell MSBuild how to build you project.

When this happens, MSBuild uses the "default" configuration and platform to build the project. If this does not match what you are building, then the wrong thing is built. (This makes me sad. L).

The "default configuration" is defined by the set of properties at the top of each project in the first <PropertyGroup />. They appear something like the following:

<PropertyGroup>

    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>

    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>

     ...

</PropertyGroup>

 

This basically says that if the Configuration is blank, use the "default" of "Debug", and if the Platform is blank, use the "default" of "AnyCPU". Since this is the behavior when the Solution Configuration does not contain information about the project being built, the default "Debug|AnyCPU" gets built. If you are building "Release", you still get "Debug" for any of these projects that are not in the solution.

You can of course change the default to anything you want. So, if you want the default to be "Release", you can simply edit this part of the file and change it to the new value.

<PropertyGroup>

    <Configuration Condition=" '$(Configuration)' == '' ">Release</Configuration>

    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>

     ...

</PropertyGroup>

 

However, this means that this is the new default (Release) that will be used for all cases where the value is not defined in the Solution Configuration. And, you would have to hand edit your project files over and over again every time you wanted to change what you are building.

A more flexible solution is to instead add the following lines:

<PropertyGroup>

    <!-- Add these two lines -->

    <Configuration Condition=" '$(Configuration)' == '' ">$(DefaultProjectConfiguration)</Configuration>

    <Platform Condition=" '$(Platform)' == '' ">$(DefaultProjectPlatform)</Platform>

 

    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>

    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>

     ...

</PropertyGroup>

 

By doing this, you can specify "/p:DefaultProjectConfiguration=Release" on the command line, which will then be used for all projects in the build where there is no "Solution Configuration" information. You can also specify "/p:DefaultProjectPlatform=AnyCPU" to set the default platform. (Note that this is less useful, since certain projects may need to build for a specific platform.)

Note that this does not change the existing behavior when $(DefaultProjectConfiguration) and $(DefaultProjectPlatform) are not supplied. And, you can specify only one of them or both of them on your command line.

This still does not allow you to configure each project individually in the build. But, it does give a lot more flexibility. And, if you really need to set the exact Configuration and Platform for a project, the Solution Configuration is the correct place to do this. But, this means that these types of projects would need to be contained in the Solution being built.

Hope this helps…