/// <summary> /// Adds a target for a project whose type is unknown and we cannot build. We will emit an error or warning as appropriate. /// </summary> private void AddMetaprojectTargetForUnknownProjectType(ProjectInstance traversalProject, ProjectInstance metaprojectInstance, ProjectInSolution project, string targetName, string unknownProjectTypeErrorMessage) { ProjectTargetInstance newTarget = metaprojectInstance.AddTarget(targetName ?? "Build", "'$(CurrentSolutionConfigurationContents)' != ''", null, null, null, null, null, false /* legacy target returns behaviour */); foreach (SolutionConfigurationInSolution solutionConfiguration in _solutionFile.SolutionConfigurations) { ProjectConfigurationInSolution projectConfiguration = null; ProjectTaskInstance newTask = null; if (project.ProjectConfigurations.TryGetValue(solutionConfiguration.FullName, out projectConfiguration)) { if (projectConfiguration.IncludeInBuild) { // Only add the task if it would run in this configuration. if (!traversalProject.EvaluateCondition(GetConditionStringForConfiguration(solutionConfiguration))) { continue; } if (unknownProjectTypeErrorMessage == null) { // we haven't encountered any problems accessing the project file in the past, but do not support // building this project type newTask = AddErrorWarningMessageInstance ( newTarget, null, XMakeElements.warning, true, "SolutionParseUnknownProjectType", project.RelativePath ); } else { // this project file may be of supported type, but we have encountered problems accessing it newTask = AddErrorWarningMessageInstance ( newTarget, null, XMakeElements.warning, true, "SolutionParseErrorReadingProject", project.RelativePath, unknownProjectTypeErrorMessage ); } } else { newTask = AddErrorWarningMessageInstance ( newTarget, null, XMakeElements.message, true, "SolutionProjectSkippedForBuilding", project.ProjectName, solutionConfiguration.FullName ); } } else { newTask = AddErrorWarningMessageInstance ( newTarget, null, XMakeElements.warning, true, "SolutionProjectConfigurationMissing", project.ProjectName, solutionConfiguration.FullName ); } } }
/// <summary> /// Add a PropertyGroup to the project for a particular Asp.Net configuration. This PropertyGroup /// will have the correct values for all the Asp.Net properties for this project and this configuration. /// </summary> private void AddPropertyGroupForAspNetConfiguration ( ProjectInstance traversalProject, ProjectInstance metaprojectInstance, ProjectInSolution project, string configurationName, AspNetCompilerParameters aspNetCompilerParameters, string solutionFile ) { // If the configuration doesn't match, don't add the properties. if (!traversalProject.EvaluateCondition(String.Format(CultureInfo.InvariantCulture, " '$(AspNetConfiguration)' == '{0}' ", EscapingUtilities.Escape(configurationName)))) { return; } // Add properties into the property group for each of the AspNetCompiler properties. // REVIEW: SetProperty takes an evaluated value. Are we doing the right thing here? metaprojectInstance.SetProperty(GenerateSafePropertyName(project, "AspNetVirtualPath"), EscapingUtilities.Escape(aspNetCompilerParameters.aspNetVirtualPath)); metaprojectInstance.SetProperty(GenerateSafePropertyName(project, "AspNetPhysicalPath"), EscapingUtilities.Escape(aspNetCompilerParameters.aspNetPhysicalPath)); metaprojectInstance.SetProperty(GenerateSafePropertyName(project, "AspNetTargetPath"), EscapingUtilities.Escape(aspNetCompilerParameters.aspNetTargetPath)); metaprojectInstance.SetProperty(GenerateSafePropertyName(project, "AspNetForce"), EscapingUtilities.Escape(aspNetCompilerParameters.aspNetForce)); metaprojectInstance.SetProperty(GenerateSafePropertyName(project, "AspNetUpdateable"), EscapingUtilities.Escape(aspNetCompilerParameters.aspNetUpdateable)); metaprojectInstance.SetProperty(GenerateSafePropertyName(project, "AspNetDebug"), EscapingUtilities.Escape(aspNetCompilerParameters.aspNetDebug)); metaprojectInstance.SetProperty(GenerateSafePropertyName(project, "AspNetKeyFile"), EscapingUtilities.Escape(aspNetCompilerParameters.aspNetKeyFile)); metaprojectInstance.SetProperty(GenerateSafePropertyName(project, "AspNetKeyContainer"), EscapingUtilities.Escape(aspNetCompilerParameters.aspNetKeyContainer)); metaprojectInstance.SetProperty(GenerateSafePropertyName(project, "AspNetDelaySign"), EscapingUtilities.Escape(aspNetCompilerParameters.aspNetDelaySign)); metaprojectInstance.SetProperty(GenerateSafePropertyName(project, "AspNetAPTCA"), EscapingUtilities.Escape(aspNetCompilerParameters.aspNetAPTCA)); metaprojectInstance.SetProperty(GenerateSafePropertyName(project, "AspNetFixedNames"), EscapingUtilities.Escape(aspNetCompilerParameters.aspNetFixedNames)); string aspNetPhysicalPath = aspNetCompilerParameters.aspNetPhysicalPath; if (!String.IsNullOrEmpty(aspNetPhysicalPath)) { // Trim the trailing slash if one exists. if ( (aspNetPhysicalPath[aspNetPhysicalPath.Length - 1] == Path.AltDirectorySeparatorChar) || (aspNetPhysicalPath[aspNetPhysicalPath.Length - 1] == Path.DirectorySeparatorChar) ) { aspNetPhysicalPath = aspNetPhysicalPath.Substring(0, aspNetPhysicalPath.Length - 1); } // This gets us the last folder in the physical path. string lastFolderInPhysicalPath = null; try { lastFolderInPhysicalPath = Path.GetFileName(aspNetPhysicalPath); } catch (Exception e) { if (ExceptionHandling.NotExpectedException(e)) { throw; } ProjectFileErrorUtilities.VerifyThrowInvalidProjectFile ( false, "SubCategoryForSolutionParsingErrors", new BuildEventFileInfo(solutionFile), e, "SolutionParseInvalidProjectFileName", project.RelativePath, e.Message ); } if (!String.IsNullOrEmpty(lastFolderInPhysicalPath)) { // If there is a global property called "OutDir" set, that means the caller is trying to // override the AspNetTargetPath. What we want to do in this case is concatenate: // $(OutDir) + "\_PublishedWebsites" + (the last portion of the folder in the AspNetPhysicalPath). if (traversalProject.EvaluateCondition(" '$(OutDir)' != '' ")) { string outDirValue = String.Empty; ProjectPropertyInstance outdir = metaprojectInstance.GetProperty("OutDir"); if (outdir != null) { outDirValue = ProjectInstance.GetPropertyValueEscaped(outdir); } // Make sure the path we are appending to has no leading slash to prevent double slashes. string publishWebsitePath = EscapingUtilities.Escape(WebProjectOverrideFolder) + Path.DirectorySeparatorChar + EscapingUtilities.Escape(lastFolderInPhysicalPath) + Path.DirectorySeparatorChar; metaprojectInstance.SetProperty ( GenerateSafePropertyName(project, "AspNetTargetPath"), outDirValue + publishWebsitePath ); } } } }
// FIXME: my guess is the tasks does not have to be loaded entirely but only requested tasks must be loaded at invocation time. void LoadUsingTasks (ProjectInstance projectInstance, IEnumerable<ProjectUsingTaskElement> usingTasks) { Func<string,bool> cond = s => projectInstance != null ? projectInstance.EvaluateCondition (s) : Convert.ToBoolean (s); foreach (var ut in usingTasks) { var ta = assemblies.FirstOrDefault (a => a.AssemblyFile.Equals (ut.AssemblyFile, StringComparison.OrdinalIgnoreCase) || a.AssemblyName.Equals (ut.AssemblyName, StringComparison.OrdinalIgnoreCase)); if (ta == null) { var path = Path.GetDirectoryName (string.IsNullOrEmpty (ut.Location.File) ? projectInstance.FullPath : ut.Location.File); ta = new TaskAssembly () { AssemblyName = ut.AssemblyName, AssemblyFile = ut.AssemblyFile }; try { ta.LoadedAssembly = !string.IsNullOrEmpty (ta.AssemblyName) ? Assembly.Load (ta.AssemblyName) : Assembly.LoadFile (Path.Combine (path, ta.AssemblyFile)); } catch { var errorNotLoaded = string.Format ("For task '{0}' Specified assembly '{1}' was not found", ut.TaskName, string.IsNullOrEmpty (ta.AssemblyName) ? ta.AssemblyFile : ta.AssemblyName); engine.LogWarningEvent (new BuildWarningEventArgs (null, null, projectInstance.FullPath, ut.Location.Line, ut.Location.Column, 0, 0, errorNotLoaded, null, null)); continue; } assemblies.Add (ta); } var pg = ut.ParameterGroup == null ? null : ut.ParameterGroup.Parameters.Select (p => new TaskPropertyInfo (p.Name, Type.GetType (p.ParameterType), cond (p.Output), cond (p.Required))) .ToDictionary (p => p.Name); Type type = null; string error = null; TaskDescription task = new TaskDescription () { TaskAssembly = ta, Name = ut.TaskName, TaskFactoryParameters = pg, TaskBody = ut.TaskBody != null && cond (ut.TaskBody.Condition) ? ut.TaskBody.Evaluate : null, }; if (string.IsNullOrEmpty (ut.TaskFactory)) { type = LoadTypeFrom (ta.LoadedAssembly, ut.TaskName, ut.TaskName); if (type == null) error = string.Format ("For task '{0}' Specified type '{1}' was not found in assembly '{2}'", ut.TaskName, ut.TaskName, ta.LoadedAssembly.FullName); else task.TaskType = type; } else { type = LoadTypeFrom (ta.LoadedAssembly, ut.TaskName, ut.TaskFactory); if (type == null) error = string.Format ("For task '{0}' Specified factory type '{1}' was not found in assembly '{2}'", ut.TaskName, ut.TaskFactory, ta.LoadedAssembly.FullName); else task.TaskFactoryType = type; } if (error != null) engine.LogWarningEvent (new BuildWarningEventArgs (null, null, projectInstance.FullPath, ut.Location.Line, ut.Location.Column, 0, 0, error, null, null)); else task_descs.Add (task); } }
/// <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(); }
void LoadUsingTasks (ProjectInstance projectInstance, ProjectRootElement project) { Func<string,bool> cond = s => projectInstance != null ? projectInstance.EvaluateCondition (s) : Convert.ToBoolean (s); foreach (var ut in project.UsingTasks) { var ta = assemblies.FirstOrDefault (a => a.AssemblyFile.Equals (ut.AssemblyFile, StringComparison.OrdinalIgnoreCase) || a.AssemblyName.Equals (ut.AssemblyName, StringComparison.OrdinalIgnoreCase)); if (ta == null) { ta = new TaskAssembly () { AssemblyName = ut.AssemblyName, AssemblyFile = ut.AssemblyFile }; ta.LoadedAssembly = ta.AssemblyName != null ? Assembly.Load (ta.AssemblyName) : Assembly.LoadFile (ta.AssemblyFile); assemblies.Add (ta); } var pg = ut.ParameterGroup == null ? null : ut.ParameterGroup.Parameters.Select (p => new TaskPropertyInfo (p.Name, Type.GetType (p.ParameterType), cond (p.Output), cond (p.Required))) .ToDictionary (p => p.Name); var task = new TaskDescription () { TaskAssembly = ta, Name = ut.TaskName, TaskFactoryType = string.IsNullOrEmpty (ut.TaskFactory) ? null : LoadTypeFrom (ta.LoadedAssembly, ut.TaskName, ut.TaskFactory), TaskType = string.IsNullOrEmpty (ut.TaskFactory) ? LoadTypeFrom (ta.LoadedAssembly, ut.TaskName, ut.TaskName) : null, TaskFactoryParameters = pg, TaskBody = ut.TaskBody != null && cond (ut.TaskBody.Condition) ? ut.TaskBody.Evaluate : null, }; task_descs.Add (task); } }