Akash Kava
Akash Kava

Reputation: 39916

Visual Studio Conditional Project Configuration Editor

I have a project, that contains many references and they all are conditional, show I have manually edited Proj files as below,

  <ItemGroup Condition=" '$(Configuration)' == 'Release' ">
    <Reference Include="Assembly1">
      <HintPath>..\Release\Path\Assembly1</HintPath>
    </Reference>
    <Reference Include="Assembly2">
      <HintPath>..\Release\Path\Assembly2</HintPath>
    </Reference>
  </ItemGroup>
  <ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
    <Reference Include="Assembly1">
      <HintPath>..\Debug\Path\Assembly1</HintPath>
    </Reference>
    <Reference Include="Assembly2">
      <HintPath>..\Debug\Path\Assembly2</HintPath>
    </Reference>
  </ItemGroup>

Note, this is just a sample, with only two Configurations, Release and Debug, currently we have 4 configurations per platform and we are dealing with storing near about 12 configurations, 3 for .NET 3.5, .NET 4 and .NET 4.5

I wonder if there is any other better way then this?

  1. Is there any visual studio plugin that allows us to do these configurations in some sort of UI rather then editing xml, because it is becoming complex day by day.
  2. Is there any scripting in MSBuild or anything that can probably read some custom xml or some datastore and we can automate this process?
  3. If I create different VSProj file for different configuration then it is very time consuming to make sure content files are added correctly, but the only problems are references.
  4. Is there any other tool that can manage references per configuration easily?

My major concern is, storing and managing references as per configuration types.

Upvotes: 2

Views: 1244

Answers (1)

Brian Kretzler
Brian Kretzler

Reputation: 9938

I'd do this:

In a file named "Common.props"

<Project ...>
  <ItemGroup> 
    <Reference Include="Assembly1"> 
      <HintPath>..\$(Configuration)\Path\Assembly1</HintPath> 
    </Reference> 
    <Reference Include="Assembly2"> 
      <HintPath>..\$(Configuration)\Path\Assembly2</HintPath> 
    </Reference> 
  </ItemGroup> 
</Project>

You can put this into a separate Common.props file as shown and use the Import element to "include" it in all of your project files, so there is a single point of maintenance, like this:

<Project ...>
  <PropertyGroup>
    <Configuration Condition="'$(Configuration)' == ''>Debug</Configuration>
    ...other properties
  </PropertyGroup>
  <Import Project="Common.props" />
  ...rest of your C# project file
</Project>

What is significant about the placement of the import shown above is that it occurs after the definition of the default value for $(Configuration), in the case that none is specified, making a proper value available in the import. You can of course move this default value declaration, plus a whole lot more, into the Common.props file. If you do this consistenly, your project files typically become little more than 4 properties (Project Guid, Namespace, Assembly Name, Project Type), an import, a list of files to compile, and any uncommon assembly references or project references. My projects typically never have any conditional properties in them, since they can almost always be factored out to a shared import.

There is no good UI to do this, the VS IDE UI is very limited and I've come to never use it for changing any project properties, but instead rely on custom tooling, generally custom MSBuild tasks to check project files to make sure they are consistent, and PowerShell scripts to modify them for common changes.

Excerpted from the book MSBuild Trickery tricks #14 - 18

EDIT: added import explanation

Upvotes: 4

Related Questions