/// <summary>
 /// Constructor
 /// </summary>
 internal ProjectConfigurationInSolution(string configurationName, string platformName, bool includeInBuild)
 {
     ConfigurationName = configurationName;
     PlatformName      = RemoveSpaceFromAnyCpuPlatform(platformName);
     IncludeInBuild    = includeInBuild;
     FullName          = SolutionConfigurationInSolution.ComputeFullName(ConfigurationName, PlatformName);
 }
        /// <summary>
        /// Figure out what solution configuration we are going to build, whether or not it actually exists in the solution
        /// file.
        /// </summary>
        private static string DetermineLikelyActiveSolutionConfiguration(SolutionFile solutionFile, IDictionary<string, string> globalProperties)
        {
            string activeSolutionConfiguration = null;
            string activeSolutionPlatform = null;

            globalProperties.TryGetValue("Configuration", out activeSolutionConfiguration);
            globalProperties.TryGetValue("Platform", out activeSolutionPlatform);

            if (String.IsNullOrEmpty(activeSolutionConfiguration))
            {
                activeSolutionConfiguration = solutionFile.GetDefaultConfigurationName();
            }

            if (String.IsNullOrEmpty(activeSolutionPlatform))
            {
                activeSolutionPlatform = solutionFile.GetDefaultPlatformName();
            }

            SolutionConfigurationInSolution configurationInSolution = new SolutionConfigurationInSolution(activeSolutionConfiguration, activeSolutionPlatform);

            return configurationInSolution.FullName;
        }
 /// <summary>
 /// A helper method for constructing conditions for a solution configuration
 /// </summary>
 /// <remarks>
 /// Sample configuration condition:
 /// '$(Configuration)' == 'Release' and '$(Platform)' == 'Any CPU'
 /// </remarks>
 private static string GetConditionStringForConfiguration(SolutionConfigurationInSolution configuration)
 {
     return string.Format
         (
         CultureInfo.InvariantCulture,
         " ('$(Configuration)' == '{0}') and ('$(Platform)' == '{1}') ",
         EscapingUtilities.Escape(configuration.ConfigurationName),
         EscapingUtilities.Escape(configuration.PlatformName)
         );
 }
 /// <summary>
 /// Adds a new property group with contents of the given solution configuration to the project.
 /// </summary>
 private void AddPropertyGroupForSolutionConfiguration(ProjectRootElement traversalProject, SolutionConfigurationInSolution solutionConfiguration)
 {
     AddPropertyGroupForSolutionConfiguration(traversalProject, _solutionFile, solutionConfiguration);
 }
        /// <summary>
        /// Adds a new property group with contents of the given solution configuration to the project
        /// Internal for unit-testing.
        /// </summary>
        internal static void AddPropertyGroupForSolutionConfiguration(ProjectRootElement msbuildProject, SolutionFile solutionFile, SolutionConfigurationInSolution solutionConfiguration)
        {
            ProjectPropertyGroupElement solutionConfigurationProperties = msbuildProject.CreatePropertyGroupElement();
            msbuildProject.AppendChild(solutionConfigurationProperties);
            solutionConfigurationProperties.Condition = GetConditionStringForConfiguration(solutionConfiguration);

            StringBuilder solutionConfigurationContents = new StringBuilder(1024);
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            settings.OmitXmlDeclaration = true;
            using (XmlWriter xw = XmlWriter.Create(solutionConfigurationContents, settings))
            {
                xw.WriteStartElement("SolutionConfiguration");

                // add a project configuration entry for each project in the solution
                foreach (ProjectInSolution project in solutionFile.ProjectsInOrder)
                {
                    ProjectConfigurationInSolution projectConfiguration = null;

                    if (project.ProjectConfigurations.TryGetValue(solutionConfiguration.FullName, out projectConfiguration))
                    {
                        xw.WriteStartElement("ProjectConfiguration");
                        xw.WriteAttributeString("Project", project.ProjectGuid);
                        xw.WriteAttributeString("AbsolutePath", project.AbsolutePath);
                        xw.WriteAttributeString("BuildProjectInSolution", projectConfiguration.IncludeInBuild.ToString());
                        xw.WriteString(projectConfiguration.FullName);

                        foreach (string dependencyProjectGuid in project.Dependencies)
                        {
                            // This is a project that the current project depends *ON* (ie., it must build first)
                            ProjectInSolution dependencyProject;
                            if (!solutionFile.ProjectsByGuid.TryGetValue(dependencyProjectGuid, out dependencyProject))
                            {
                                // If it's not itself part of the solution, that's an invalid solution
                                ProjectFileErrorUtilities.VerifyThrowInvalidProjectFile(dependencyProject != null, "SubCategoryForSolutionParsingErrors", new BuildEventFileInfo(solutionFile.FullPath), "SolutionParseProjectDepNotFoundError", project.ProjectGuid, dependencyProjectGuid);
                            }

                            // Add it to the list of dependencies, but only if it should build in this solution configuration 
                            // (If a project is not selected for build in the solution configuration, it won't build even if it's depended on by something that IS selected for build)
                            // .. and only if it's known to be MSBuild format, as projects can't use the information otherwise 
                            if (dependencyProject.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat)
                            {
                                ProjectConfigurationInSolution dependencyProjectConfiguration = null;
                                if (dependencyProject.ProjectConfigurations.TryGetValue(solutionConfiguration.FullName, out dependencyProjectConfiguration) &&
                                    WouldProjectBuild(solutionFile, solutionConfiguration.FullName, dependencyProject, dependencyProjectConfiguration))
                                {
                                    xw.WriteStartElement("ProjectDependency");
                                    xw.WriteAttributeString("Project", dependencyProjectGuid);
                                    xw.WriteEndElement();
                                }
                            }
                        }

                        xw.WriteEndElement(); // </ProjectConfiguration>
                    }
                }

                xw.WriteEndElement(); // </SolutionConfiguration>
            }

            var escapedSolutionConfigurationContents = EscapingUtilities.Escape(solutionConfigurationContents.ToString());

            solutionConfigurationProperties.AddProperty("CurrentSolutionConfigurationContents", escapedSolutionConfigurationContents);

            msbuildProject.AddItem(
                "SolutionConfiguration",
                solutionConfiguration.FullName,
                new Dictionary<string, string>
                {
                    { "Configuration", solutionConfiguration.ConfigurationName },
                    { "Platform", solutionConfiguration.PlatformName },
                    { "Content", escapedSolutionConfigurationContents },
                });
        }
        /// <summary>
        /// Adds MSBuild tasks to a project target to pre-resolve its project references
        /// </summary>
        private void AddResolveProjectReferenceTasks
        (
            ProjectInstance traversalProject,
            ProjectTargetInstance target,
            ProjectInSolution project,
            SolutionConfigurationInSolution solutionConfiguration,
            string outputReferenceItemName,
            string outputImportLibraryItemName,
            out string addedReferenceGuids
        )
        {
            StringBuilder referenceGuids = new StringBuilder();

            string message = null;

            // Suffix for the reference item name. Since we need to attach additional (different) metadata to every
            // reference item, we need to have helper item lists each with only one item
            int outputReferenceItemNameSuffix = 0;

            // Pre-resolve the MSBuild project references
            foreach (string projectReferenceGuid in project.ProjectReferences)
            {
                ProjectInSolution referencedProject = (ProjectInSolution)_solutionFile.ProjectsByGuid[projectReferenceGuid];
                ProjectConfigurationInSolution referencedProjectConfiguration = null;

                if ((referencedProject != null) &&
                    (referencedProject.ProjectConfigurations.TryGetValue(solutionConfiguration.FullName, out referencedProjectConfiguration)) &&
                    (referencedProjectConfiguration != null))
                {
                    string outputReferenceItemNameWithSuffix = string.Format(CultureInfo.InvariantCulture, "{0}_{1}", outputReferenceItemName, outputReferenceItemNameSuffix);

                    if ((referencedProject.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat) ||
                        ((referencedProject.ProjectType == SolutionProjectType.Unknown) && (referencedProject.CanBeMSBuildProjectFile(out message))))
                    {
                        string condition = GetConditionStringForConfiguration(solutionConfiguration);
                        if (traversalProject.EvaluateCondition(condition))
                        {
                            bool specifyProjectToolsVersion =
                                String.Equals(traversalProject.ToolsVersion, "2.0", StringComparison.OrdinalIgnoreCase) ? false : true;

                            ProjectTaskInstance msbuildTask = AddMSBuildTaskInstance
                                (
                                target,
                                referencedProject.RelativePath,
                                "GetTargetPath",
                                referencedProjectConfiguration.ConfigurationName,
                                referencedProjectConfiguration.PlatformName,
                                specifyProjectToolsVersion
                                );
                            msbuildTask.AddOutputItem("TargetOutputs", outputReferenceItemNameWithSuffix, null);
                        }

                        if (referenceGuids.Length > 0)
                        {
                            referenceGuids.Append(';');
                        }

                        referenceGuids.Append(projectReferenceGuid);

                        // This merges the one-item item list into the main list, adding the appropriate guid metadata
                        ProjectTaskInstance createItemTask = target.AddTask("CreateItem", null, null);
                        createItemTask.SetParameter("Include", "@(" + outputReferenceItemNameWithSuffix + ")");
                        createItemTask.SetParameter("AdditionalMetadata", "Guid=" + projectReferenceGuid);
                        createItemTask.AddOutputItem("Include", outputReferenceItemName, null);
                    }

                    outputReferenceItemNameSuffix++;
                }
            }

            addedReferenceGuids = referenceGuids.ToString();
        }