/// <summary> /// Adds tasks that create a temporary VC project file with pre-resolved project references (that is, /// replaced with file references) /// </summary> /// <param name="solution"></param> /// <param name="target"></param> /// <param name="proj"></param> /// <param name="solutionConfiguration"></param> /// <param name="subTargetName"></param> /// <param name="projectConfigurationName"></param> /// <returns>The path to the temporary project file</returns> /// <owner>LukaszG</owner> static private string AddCreateTemporaryVCProjectTasks ( SolutionParser solution, Project msbuildProject, Target target, ProjectInSolution proj, ConfigurationInSolution solutionConfiguration, string subTargetName, string projectConfigurationName ) { StringBuilder referenceItemName = new StringBuilder(GenerateSafePropertyName(proj, "References")); if (!string.IsNullOrEmpty(subTargetName)) { referenceItemName.Append('_'); referenceItemName.Append(subTargetName); } StringBuilder importLibraryItemName = new StringBuilder(GenerateSafePropertyName(proj, "ImportLibraries")); if (!string.IsNullOrEmpty(subTargetName)) { importLibraryItemName.Append('_'); importLibraryItemName.Append(subTargetName); } string referenceGuidsToRemove = null; AddResolveProjectReferenceTasks(solution, msbuildProject, target, proj, solutionConfiguration, referenceItemName.ToString(), importLibraryItemName.ToString(), out referenceGuidsToRemove); if (string.IsNullOrEmpty(referenceGuidsToRemove)) referenceGuidsToRemove = string.Empty; string fullProjectPath = null; string tmpExtension = null; string projectPath = null; try { fullProjectPath = proj.AbsolutePath; tmpExtension = string.Format(CultureInfo.InvariantCulture, ".tmp_{0}_{1}.vcproj", solutionConfiguration.ConfigurationName, solutionConfiguration.PlatformName); projectPath = Path.ChangeExtension(fullProjectPath, tmpExtension); } catch (Exception e) { if (ExceptionHandling.NotExpectedException(e)) throw; ProjectFileErrorUtilities.VerifyThrowInvalidProjectFile(false, "SubCategoryForSolutionParsingErrors", new BuildEventFileInfo(solution.SolutionFile), "SolutionParseInvalidProjectFileName", proj.RelativePath, e.Message); } // Create the temporary VC project BuildTask createVCProjectTask = target.AddNewTask("CreateTemporaryVCProject"); createVCProjectTask.SetParameterValue("ProjectFile", fullProjectPath, true /* treat as literal */); createVCProjectTask.SetParameterValue("Configuration", projectConfigurationName, true /* treat as literal */); createVCProjectTask.SetParameterValue("OutputProjectFile", projectPath, true /* treat as literal */); createVCProjectTask.SetParameterValue("ReferenceGuids", referenceGuidsToRemove, false /* Contains semicolon-separated list. DO NOT treat as literal */); createVCProjectTask.SetParameterValue("ReferenceAssemblies", string.Format(CultureInfo.InvariantCulture, "@({0})", referenceItemName.ToString()), false /* DO NOT treat as literal */); createVCProjectTask.SetParameterValue("ReferenceImportLibraries", string.Format(CultureInfo.InvariantCulture, "@({0})", importLibraryItemName.ToString()), false /* DO NOT treat as literal */); createVCProjectTask.Condition = GetConditionStringForConfiguration(solutionConfiguration); return projectPath; }
/// <summary> /// Adds MSBuild and ResolveVCProjectOutput tasks to a project target to pre-resolve its project references /// </summary> /// <param name="solution"></param> /// <param name="target"></param> /// <param name="proj"></param> /// <param name="solutionConfiguration"></param> /// <param name="outputReferenceItemName"></param> /// <param name="outputImportLibraryItemName"></param> /// <param name="addedReferenceGuids"></param> /// <owner>LukaszG</owner> static private void AddResolveProjectReferenceTasks ( SolutionParser solution, Project msbuildProject, Target target, ProjectInSolution proj, ConfigurationInSolution 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/VC project references foreach (string projectReferenceGuid in proj.ProjectReferences) { ProjectInSolution referencedProject = (ProjectInSolution)solution.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); bool addCreateItem = false; if ((referencedProject.ProjectType == SolutionProjectType.ManagedProject) || ((referencedProject.ProjectType == SolutionProjectType.Unknown) && (referencedProject.CanBeMSBuildProjectFile(out message)))) { string condition = GetConditionStringForConfiguration(solutionConfiguration); bool specifyProjectToolsVersion = String.Equals(msbuildProject.ToolsVersion, "2.0", StringComparison.OrdinalIgnoreCase) ? false : true; BuildTask msbuildTask = AddMSBuildTaskElement(target, referencedProject.RelativePath, "GetTargetPath", referencedProjectConfiguration.ConfigurationName, referencedProjectConfiguration.PlatformName, specifyProjectToolsVersion); msbuildTask.Condition = condition; msbuildTask.AddOutputItem("TargetOutputs", outputReferenceItemNameWithSuffix); if (referenceGuids.Length > 0) { referenceGuids.Append(';'); } referenceGuids.Append(projectReferenceGuid); addCreateItem = true; } else if (referencedProject.ProjectType == SolutionProjectType.VCProject) { BuildTask vcbuildTask = null; try { vcbuildTask = AddResolveVCProjectOutputTaskElement(target, Path.Combine(solution.SolutionFileDirectory, Path.GetFileName(solution.SolutionFile)), referencedProject.AbsolutePath, referencedProjectConfiguration.FullName); } catch (Exception e) { if (ExceptionHandling.NotExpectedException(e)) throw; ProjectFileErrorUtilities.VerifyThrowInvalidProjectFile(false, "SubCategoryForSolutionParsingErrors", new BuildEventFileInfo(solution.SolutionFile), "SolutionParseInvalidProjectFileName", referencedProject.RelativePath, e.Message); } vcbuildTask.Condition = GetConditionStringForConfiguration(solutionConfiguration); vcbuildTask.AddOutputItem("ResolvedOutputPaths", outputReferenceItemNameWithSuffix); if (outputImportLibraryItemName != null) { vcbuildTask.AddOutputItem("ResolvedImportLibraryPaths", outputImportLibraryItemName); } if (referenceGuids.Length > 0) { referenceGuids.Append(';'); } referenceGuids.Append(projectReferenceGuid); addCreateItem = true; } // Add create item if either of the conditions above was true. // This merges the one-item item list into the main list, adding the appropriate guid metadata if (addCreateItem) { BuildTask createItemTask = target.AddNewTask("CreateItem"); createItemTask.SetParameterValue("Include", "@(" + outputReferenceItemNameWithSuffix + ")", false /* do not treat as literal */); createItemTask.SetParameterValue("AdditionalMetadata", "Guid=" + projectReferenceGuid, false /* do not treat as literal */); createItemTask.AddOutputItem("Include", outputReferenceItemName); } outputReferenceItemNameSuffix++; } } addedReferenceGuids = referenceGuids.ToString(); }
/// <summary> /// Adds a new property group with contents of the given solution configuration to the project /// Internal for unit-testing. /// </summary> /// <param name="msbuildProject"></param> /// <param name="solution"></param> /// <param name="solutionConfiguration"></param> /// <owner>LukaszG</owner> static internal void AddPropertyGroupForSolutionConfiguration ( Project msbuildProject, SolutionParser solution, ConfigurationInSolution solutionConfiguration ) { BuildPropertyGroup propertyGroup = msbuildProject.AddNewPropertyGroup(true /* insertAtEndOfProject = true */); propertyGroup.Condition = GetConditionStringForConfiguration(solutionConfiguration); StringBuilder solutionConfigurationContents = new StringBuilder("<SolutionConfiguration>"); // add a project configuration entry for each project in the solution foreach (ProjectInSolution project in solution.ProjectsInOrder) { ProjectConfigurationInSolution projectConfiguration = null; if (project.ProjectConfigurations.TryGetValue(solutionConfiguration.FullName, out projectConfiguration)) { solutionConfigurationContents.AppendFormat( CultureInfo.InvariantCulture, "<ProjectConfiguration Project=\"{0}\">{1}</ProjectConfiguration>", project.ProjectGuid, projectConfiguration.FullName ); } } solutionConfigurationContents.Append("</SolutionConfiguration>"); propertyGroup.AddNewProperty("CurrentSolutionConfigurationContents", solutionConfigurationContents.ToString(), true /* treat as literal */); }
/// <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(SolutionParser solution, Engine parentEngine) { string activeSolutionConfiguration; string activeSolutionPlatform; BuildProperty configurationProperty = parentEngine.GlobalProperties["Configuration"]; BuildProperty platformProperty = parentEngine.GlobalProperties["Platform"]; if (configurationProperty != null) { activeSolutionConfiguration= configurationProperty.FinalValue; } else { activeSolutionConfiguration = solution.GetDefaultConfigurationName(); } if (platformProperty != null) { activeSolutionPlatform = platformProperty.FinalValue; } else { activeSolutionPlatform = solution.GetDefaultPlatformName(); } ConfigurationInSolution configurationInSolution = new ConfigurationInSolution(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> /// <param name="configuration"></param> /// <returns></returns> /// <owner>LukaszG</owner> static private string GetConditionStringForConfiguration(ConfigurationInSolution configuration) { return string.Format(CultureInfo.InvariantCulture, " ('$(Configuration)' == '{0}') and ('$(Platform)' == '{1}') ", EscapingUtilities.Escape(configuration.ConfigurationName), EscapingUtilities.Escape(configuration.PlatformName)); }