Ejemplo n.º 1
0
    /// <summary>
    /// Saves solution into .sln file. Where to save is defined by path.
    /// </summary>
    /// <param name="_path">path to .sln, null if use from 'path' variable.</param>
    /// <param name="uinfo">Update information</param>
    public void SaveSolution(UpdateInfo uinfo, String _path = null)
    {
        String slnPath = _path;

        if (_path == null)
        {
            slnPath = path;
        }

        //
        //  For all projects which does not have uuid, we generated uuid based on project name.
        //
        SolutionProjectBuilder.externalproject(null);   // Release any active project if we have one.

        if (fileFormatVersion >= 2017 && String.IsNullOrEmpty(SolutionGuid))
        {
            SolutionProjectBuilder.uuid(name + "_solution" /* Add some uniqueness - just not to collise with project guids. */);
        }

        foreach (Project p in projects)
        {
            if (String.IsNullOrEmpty(p.ProjectGuid))
            {
                SolutionProjectBuilder.m_project = p;
                SolutionProjectBuilder.uuid(p.ProjectName);
                SolutionProjectBuilder.m_project = null;
            }
        } //foreach

        StringBuilder o = new StringBuilder();

        o.AppendLine();

        int verTag = fileFormatVersion;

        if (verTag == 0)
        {
            verTag = 2015;
        }

        String formatVersion = "12.00";

        if (verTag <= 2010)
        {
            formatVersion = "11.00";
        }

        o.AppendLine("Microsoft Visual Studio Solution File, Format Version " + formatVersion);

        int verTag2;

        switch (verTag)
        {
        case 2015: verTag2 = 14; break;

        case 2017: verTag2 = 15; break;

        case 2019: verTag2 = 16; break;

        default:
            // Try to predict the future here...
            verTag2 = 14 + (verTag - 2015) / 2;
            break;
        }

        if (verTag2 >= 16)
        {
            o.AppendLine("# Visual Studio Version " + verTag2.ToString());
        }
        else
        {
            o.AppendLine("# Visual Studio " + verTag2.ToString());
        }

        // Must be specified, otherwise Visual studio will try to save project after load.
        if (fileFormatVersion >= 2017)
        {
            // Those numbers are pretty ugly to hardcode, but no other choice at the moment.
            String ver = VisualStudioVersion;
            if (ver == null)
            {
                switch (fileFormatVersion)
                {
                case 2017: ver = "15.0.28307.136"; break;

                default:
                case 2019: ver = "16.0.28315.86"; break;
                }
            }

            o.AppendLine("VisualStudioVersion = " + ver);
        }

        // Must be specified, otherwise Visual studio will try to save project after load.
        if (fileFormatVersion >= 2015)
        {
            String ver = MinimumVisualStudioVersion;
            if (ver == null)
            {
                ver = "10.0.40219.1";
            }
            o.AppendLine("MinimumVisualStudioVersion = " + ver);
        }

        // Visual studio 2015 itself dumps also VisualStudioVersion & MinimumVisualStudioVersion - but we cannot support it, as it's targetted per visual studio toolset version.

        //
        // Dump projects.
        //
        foreach (Project p in projects)
        {
            o.AppendLine("Project(\"" + p.ProjectHostGuid + "\") = \"" + p.ProjectName + "\", \"" + p.getRelativePath() + "\", \"" + p.ProjectGuid.ToUpper() + "\"");

            //
            // Dump project dependencies.
            //
            if (p.ProjectDependencies != null)
            {
                o.AppendLine("	ProjectSection(ProjectDependencies) = postProject");
                foreach (String depProjName in p.ProjectDependencies)
                {
                    String guid = null;

                    // Dependency specified by {guid}
                    if (SolutionProjectBuilder.guidMatcher.Match(depProjName).Success)
                    {
                        guid = depProjName;
                    }
                    else
                    {
                        // Dependency specified by project name
                        Project dproj = projects.Where(x => x.ProjectName == depProjName).FirstOrDefault();
                        if (dproj != null)
                        {
                            guid = dproj.ProjectGuid.ToUpper();
                        }
                    }

                    if (guid != null)
                    {
                        o.AppendLine("		"+ guid + " = " + guid);
                    }
                }
                o.AppendLine("	EndProjectSection");
            } //if

            o.AppendLine("EndProject");
        }


        List <String> sortedConfs = Project.getSortedConfigurations(configurations, false, null, true);

        //
        // Dump configurations.
        //
        o.AppendLine("Global");
        o.AppendLine("	GlobalSection(SolutionConfigurationPlatforms) = preSolution");
        foreach (String cfg in sortedConfs)
        {
            o.AppendLine("		"+ cfg + " = " + cfg);
        }
        o.AppendLine("	EndGlobalSection");


        //
        // Dump solution to project configuration mapping and whether or not to build specific project.
        //
        o.AppendLine("	GlobalSection(ProjectConfigurationPlatforms) = postSolution");
        foreach (Project p in projects)
        {
            if (p.IsSubFolder())        // If sub-folder no need to list it here.
            {
                continue;
            }

            List <String> projConfs     = p.getConfigurationNames();
            List <String> projPlatforms = p.getPlatforms();

            foreach (String conf in sortedConfs)
            {
                int    iConf      = configurations.IndexOf(conf);
                String mappedConf = conf;

                bool bPeformBuild   = true;
                bool?bPerformDeploy = null;

                if (p.bIsPackagingProject)
                {
                    bPerformDeploy = true;
                }

                if (p.slnConfigurations != null && iConf < p.slnConfigurations.Count)
                {
                    // Mapped configuration item is specified.
                    mappedConf = p.slnConfigurations[iConf];
                }
                else
                {
                    if (p.bDefinedAsExternal)
                    {
                        // Hack - assume one to one mapping for timebeing.
                        mappedConf = conf;
                    }
                    else
                    {
                        //
                        // Try to map configuration by ourselfs. Map x86 to Win32 automatically.
                        //
                        if (!p.configurations.Contains(conf))
                        {
                            String[] confPlat = conf.Split('|');

                            if (projConfs.Contains(confPlat[0]) && confPlat[1] == "x86" && projPlatforms.Contains("Win32"))
                            {
                                mappedConf = confPlat[0] + '|' + "Win32";
                            }
                            else
                            {
                                // Configuration cannot be mapped (E.g. Solution has "Debug|Arm", project supports only "Debug|Win32".
                                // We disable project build, but try to map configuration anyway - otherwise Visual Studio will
                                // try to save solution by itself.
                                bPeformBuild   = false;
                                bPerformDeploy = null;

                                mappedConf = p.configurations.Where(x => x.StartsWith(confPlat[0])).FirstOrDefault();
                                if (mappedConf == null)
                                {
                                    mappedConf = p.configurations[0];
                                }
                            } //if-else
                        }     //if
                    }
                }

                if (p.slnBuildProject != null && iConf < p.slnBuildProject.Count)
                {
                    bPeformBuild = p.slnBuildProject[iConf];
                }

                if (p.slnDeployProject != null && iConf < p.slnConfigurations.Count)
                {
                    bPerformDeploy = p.slnDeployProject[iConf];
                }

                o.AppendLine("		"+ p.ProjectGuid.ToUpper() + "." + conf + ".ActiveCfg = " + mappedConf);
                if (bPeformBuild)
                {
                    o.AppendLine("		"+ p.ProjectGuid.ToUpper() + "." + conf + ".Build.0 = " + mappedConf);
                }

                if (bPerformDeploy.HasValue && bPerformDeploy.Value)
                {
                    o.AppendLine("		"+ p.ProjectGuid.ToUpper() + "." + conf + ".Deploy.0 = " + mappedConf);
                }
            } //for
        }     //foreach
        o.AppendLine("	EndGlobalSection");
        o.AppendLine("	GlobalSection(SolutionProperties) = preSolution");
        o.AppendLine("		HideSolutionNode = FALSE");
        o.AppendLine("	EndGlobalSection");

        //
        // Dump project dependency hierarchy.
        //
        Project root = projects.FirstOrDefault();

        if (root != null)
        {
            while (root.parent != null)
            {
                root = root.parent;
            }

            //
            // Flatten tree without recursion.
            //
            int            treeIndex = 0;
            List <Project> projects2 = new List <Project>();
            projects2.AddRange(root.nodes);

            for (; treeIndex < projects2.Count; treeIndex++)
            {
                if (projects2[treeIndex].nodes.Count == 0)
                {
                    continue;
                }
                projects2.AddRange(projects2[treeIndex].nodes);
            }

            bool bDump = projects2.Count(x => x.parent.parent != null) != 0;

            if (bDump)
            {
                o.AppendLine("	GlobalSection(NestedProjects) = preSolution");
            }

            foreach (Project p in projects2)
            {
                if (p.parent.parent == null)
                {
                    continue;
                }
                o.AppendLine("		"+ p.ProjectGuid.ToUpper() + " = " + p.parent.ProjectGuid.ToUpper());
            }

            if (bDump)
            {
                o.AppendLine("	EndGlobalSection");
            }
        } //if

        if (SolutionGuid != null)
        {
            o.AppendLine("	GlobalSection(ExtensibilityGlobals) = postSolution");
            o.AppendLine("		SolutionGuid = "+ SolutionGuid);
            o.AppendLine("	EndGlobalSection");
        }

        o.AppendLine("EndGlobal");

        String currentSln = "";

        if (File.Exists(slnPath))
        {
            currentSln = File.ReadAllText(slnPath);
        }

        String newSln = o.ToString();

        //
        // Save only if needed.
        //
        if (currentSln == newSln)
        {
            uinfo.MarkFileUpdated(slnPath, false);
        }
        else
        {
            if (SolutionProjectBuilder.isDeveloper() && File.Exists(slnPath))
            {
                File.Copy(slnPath, slnPath + ".bkp", true);
            }
            File.WriteAllText(slnPath, newSln, Encoding.UTF8);
            uinfo.MarkFileUpdated(slnPath, true);
        } //if-else
    }     //SaveSolution