Home > database >  How to programatically analyse solution configuration mappings
How to programatically analyse solution configuration mappings

Time:11-03

We are trying to use the Microsoft.Build NuGet package to be able to programatically analyse the configuration mapping in solution files.

As an example to be able to detect when a project is being built using Debug when the solution is being built using Release.

We are able to use the SolutionFile.Parse to load the solution file but it's not clear how the configuration mapping can be analysed.

Is it possible to do something like this?

CodePudding user response:

I created a blank solution, added a project, and then edited the configurations in the solution and in the project to add a 'Sln' and a 'Proj' prefix, respectively. The solution has 'SlnDebug' and 'SlnRelease'. The project has 'ProjDebug' and 'ProjRelease'.

This yields the following SLN file:


Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.3.32929.385
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Project", "Project\Project.csproj", "{6056F2E8-3ED1-4992-92B6-2BD1D721F940}"
EndProject
Global
    GlobalSection(SolutionConfigurationPlatforms) = preSolution
        SlnDebug|Any CPU = SlnDebug|Any CPU
        SlnRelease|Any CPU = SlnRelease|Any CPU
    EndGlobalSection
    GlobalSection(ProjectConfigurationPlatforms) = postSolution
        {6056F2E8-3ED1-4992-92B6-2BD1D721F940}.SlnDebug|Any CPU.ActiveCfg = ProjDebug|Any CPU
        {6056F2E8-3ED1-4992-92B6-2BD1D721F940}.SlnDebug|Any CPU.Build.0 = ProjDebug|Any CPU
        {6056F2E8-3ED1-4992-92B6-2BD1D721F940}.SlnRelease|Any CPU.ActiveCfg = ProjDebug|Any CPU
        {6056F2E8-3ED1-4992-92B6-2BD1D721F940}.SlnRelease|Any CPU.Build.0 = ProjDebug|Any CPU
    EndGlobalSection
    GlobalSection(SolutionProperties) = preSolution
        HideSolutionNode = FALSE
    EndGlobalSection
    GlobalSection(ExtensibilityGlobals) = postSolution
        SolutionGuid = {C9B115D6-91A4-4330-B2C6-8BDCA08881F0}
    EndGlobalSection
EndGlobal

The following lines map the solution's Configuration|Platform of 'SlnDebug|Any CPU' to the project's Configuration|Platform of 'ProjDebug|Any CPU'.

        {6056F2E8-3ED1-4992-92B6-2BD1D721F940}.SlnDebug|Any CPU.ActiveCfg = ProjDebug|Any CPU
        {6056F2E8-3ED1-4992-92B6-2BD1D721F940}.SlnDebug|Any CPU.Build.0 = ProjDebug|Any CPU

Using this SLN file as a test file will help to understand what SolutionFile.Parse(string solutionFile) is doing. Also see "Solution (.sln) file" for documentation on the file format.

The following code example parses a solution file and compares the solution level and project level Configuration and Platform values.

using Microsoft.Build.Construction;

const string slnFilePath = @"<test solution file path and name>";

var solution = SolutionFile.Parse(slnFilePath);

foreach (var project in solution.ProjectsInOrder)
{
    Console.WriteLine($"Project '{project.ProjectName}'");
    foreach (var pair in project.ProjectConfigurations)
    {
        Console.WriteLine($"  Solution Configuration|Platform '{pair.Key}'");

        var (slnConfiguration, slnPlatform) = pair.Key.Split('|', 2, StringSplitOptions.TrimEntries) switch { var strs => (strs[0], strs[1]) };

        var projConfiguration = pair.Value.ConfigurationName;
        var projPlatform = pair.Value.PlatformName;

        Console.WriteLine($"    '{slnConfiguration}' {(slnConfiguration == projConfiguration ? "matches" : "does not match") } '{projConfiguration}'.");

        // Special case for 'Any CPU' and 'AnyCPU'.
        if (slnPlatform == "Any CPU" && projPlatform == "AnyCPU")
        {
            Console.WriteLine($"    '{slnPlatform}' matches '{projPlatform}'.");
        }
        else
        {
            Console.WriteLine($"    '{slnPlatform}' {(slnPlatform == projPlatform ? "matches" : "does not match")} '{projPlatform}'.");
        }
    }
}

Note the special case for 'Any CPU'. For legacy reasons, solutions use 'Any CPU' (with a space) and projects use 'AnyCPU' (with no space) and this should be treated as a matching platform.

This example code is intended to illustrate how the SolutionFile object returned by Parse() can be used and hopefully this makes the mapping clearer.

  • Related