Example #1
0
            /// <summary>
            /// Adds a ProjectToBuild item for the project and it's project references.
            /// Returns the added item, or null if an error occured.
            /// </summary>
            ProjectToBuild ParseMSBuildProject(IProject project)
            {
                ProjectToBuild ptb;

                if (parseMSBuildProjectProjectsToBuildDict.TryGetValue(project, out ptb))
                {
                    // only add each project once, reuse existing ProjectToBuild
                    return(ptb);
                }
                ptb = new ProjectToBuild(project.FileName, options.Target.TargetName);
                ptb.configuration = parentEngine.Configuration;
                ptb.platform      = parentEngine.Platform;

                projectsToBuild.Add(ptb);
                parseMSBuildProjectProjectsToBuildDict[project] = ptb;

                foreach (ProjectItem item in project.GetItemsOfType(ItemType.ProjectReference))
                {
                    ProjectReferenceProjectItem prpi = item as ProjectReferenceProjectItem;
                    if (prpi != null && prpi.ReferencedProject != null)
                    {
                        ProjectToBuild referencedProject = ParseMSBuildProject(prpi.ReferencedProject);
                        if (referencedProject == null)
                        {
                            return(null);
                        }
                        ptb.dependencies.Add(referencedProject);
                    }
                }

                return(ptb);
            }
Example #2
0
            /// <summary>
            /// Find available work and run it on the specified worker.
            /// </summary>
            bool RunWorkerInternal(MSBuildEngineWorker worker)
            {
                ProjectToBuild nextFreeProject = null;

                lock (projectsToBuild) {
                    foreach (ProjectToBuild ptb in projectsToBuild)
                    {
                        if (ptb.buildStarted == false && ptb.DependenciesSatisfied())
                        {
                            if (nextFreeProject == null)
                            {
                                nextFreeProject = ptb;

                                // all workers busy, don't look if there is more work available
                                if (workerCount == maxWorkerCount)
                                {
                                    break;
                                }
                            }
                            else
                            {
                                // free workers available + additional work available:
                                // start a new worker
                                LoggingService.Debug("Starting a new worker");
                                workerCount++;
                                Thread thread = new Thread(RunWorkerBuild);
                                thread.Name = "MSBuildEngine worker " + (++lastUniqueWorkerID);
                                thread.SetApartmentState(ApartmentState.STA);
                                thread.Start();

                                // start at most one additional worker, the new worker can
                                // start more threads if desired
                                break;
                            }
                        }
                    }
                    if (nextFreeProject == null)
                    {
                        // nothing to do for this worker thread
                        return(false);
                    }
                    // now build nextFreeProject
                    nextFreeProject.buildStarted = true;
                }                 // end lock

                StatusBarService.SetMessage("${res:MainWindow.CompilerMessages.BuildVerb} " + Path.GetFileNameWithoutExtension(nextFreeProject.file) + "...");

                // run the build:
                if (worker.Build(nextFreeProject))
                {
                    // build successful: mark it as finished
                    lock (projectsToBuild) {
                        nextFreeProject.buildFinished = true;
                    }
                }
                return(true);
            }
Example #3
0
 /// <summary>
 /// Recursively increment requiredByCount on ptb and all its dependencies
 /// </summary>
 static void IncrementRequiredByCount(ProjectToBuild ptb)
 {
     if (ptb.visitFlag == 1)
     {
         return;
     }
     if (ptb.visitFlag == -1)
     {
         throw new DependencyCycleException();
     }
     ptb.visitFlag = -1;
     ptb.requiredByCount++;
     ptb.dependencies.ForEach(IncrementRequiredByCount);
     ptb.visitFlag = 1;
 }
Example #4
0
            bool ParseSolution(Project solution)
            {
                // get the build target to call
                Target mainBuildTarget = solution.Targets[options.Target.TargetName];

                if (mainBuildTarget == null)
                {
                    currentResults.Result = BuildResultCode.BuildFileError;
                    currentResults.Add(new BuildError(this.solution.FileName, "Target '" + options.Target + "' not supported by solution."));
                    return(false);
                }
                // example of mainBuildTarget:
                //  <Target Name="Build" Condition="'$(CurrentSolutionConfigurationContents)' != ''">
                //    <CallTarget Targets="Main\ICSharpCode_SharpDevelop;Main\ICSharpCode_Core;Main\StartUp;Tools" RunEachTargetSeparately="true" />
                //  </Target>
                List <BuildTask> mainBuildTargetTasks = Linq.ToList(Linq.CastTo <BuildTask>(mainBuildTarget));

                if (mainBuildTargetTasks.Count != 1 ||
                    mainBuildTargetTasks[0].Name != "CallTarget")
                {
                    return(InvalidTarget(mainBuildTarget));
                }

                List <Target> solutionTargets = new List <Target>();

                foreach (string solutionTargetName in mainBuildTargetTasks[0].GetParameterValue("Targets").Split(';'))
                {
                    Target target = solution.Targets[solutionTargetName];
                    if (target != null)
                    {
                        solutionTargets.Add(target);
                    }
                }

                // dictionary for fast lookup of ProjectToBuild elements
                Dictionary <string, ProjectToBuild> projectsToBuildDict = new Dictionary <string, ProjectToBuild>();

                // now look through targets that took like this:
                //  <Target Name="Main\ICSharpCode_Core" Condition="'$(CurrentSolutionConfigurationContents)' != ''">
                //    <MSBuild Projects="Main\Core\Project\ICSharpCode.Core.csproj" Properties="Configuration=Debug; Platform=AnyCPU; BuildingSolutionFile=true; CurrentSolutionConfigurationContents=$(CurrentSolutionConfigurationContents); SolutionDir=$(SolutionDir); SolutionExt=$(SolutionExt); SolutionFileName=$(SolutionFileName); SolutionName=$(SolutionName); SolutionPath=$(SolutionPath)" Condition=" ('$(Configuration)' == 'Debug') and ('$(Platform)' == 'Any CPU') " />
                //    <MSBuild Projects="Main\Core\Project\ICSharpCode.Core.csproj" Properties="Configuration=Release; Platform=AnyCPU; BuildingSolutionFile=true; CurrentSolutionConfigurationContents=$(CurrentSolutionConfigurationContents); SolutionDir=$(SolutionDir); SolutionExt=$(SolutionExt); SolutionFileName=$(SolutionFileName); SolutionName=$(SolutionName); SolutionPath=$(SolutionPath)" Condition=" ('$(Configuration)' == 'Release') and ('$(Platform)' == 'Any CPU') " />
                //  </Target>
                // and add those targets to the "projectsToBuild" list.
                foreach (Target target in solutionTargets)
                {
                    List <BuildTask> tasks = Linq.ToList(Linq.CastTo <BuildTask>(target));
                    if (tasks.Count == 0)
                    {
                        return(InvalidTarget(target));
                    }

                    // find task to run when this target is executed
                    BuildTask bestTask = null;
                    foreach (BuildTask task in tasks)
                    {
                        if (task.Name != "MSBuild")
                        {
                            return(InvalidTarget(target));
                        }
                        if (MSBuildInternals.EvaluateCondition(solution, task.Condition))
                        {
                            bestTask = task;
                        }
                    }
                    if (bestTask == null)
                    {
                        LoggingService.Warn("No matching condition for solution target " + target.Name);
                        bestTask = tasks[0];
                    }

                    // create projectToBuild entry and add it to list and dictionary
                    string         projectFileName = Path.Combine(this.solution.Directory, bestTask.GetParameterValue("Projects"));
                    ProjectToBuild projectToBuild  = new ProjectToBuild(Path.GetFullPath(projectFileName),
                                                                        bestTask.GetParameterValue("Targets"));

                    // get project configuration and platform from properties section
                    string propertiesString = bestTask.GetParameterValue("Properties");
                    Match  match            = Regex.Match(propertiesString, @"\bConfiguration=([^;]+);");
                    if (match.Success)
                    {
                        projectToBuild.configuration = match.Groups[1].Value;
                    }
                    else
                    {
                        projectToBuild.configuration = parentEngine.Configuration;
                    }
                    match = Regex.Match(propertiesString, @"\bPlatform=([^;]+);");
                    if (match.Success)
                    {
                        projectToBuild.platform = match.Groups[1].Value;
                    }
                    else
                    {
                        projectToBuild.platform = parentEngine.Platform;
                        if (projectToBuild.platform == "Any CPU")
                        {
                            projectToBuild.platform = "AnyCPU";
                        }
                    }

                    projectsToBuild.Add(projectToBuild);
                    projectsToBuildDict[target.Name] = projectToBuild;
                }

                // now create dependencies between projectsToBuild
                foreach (Target target in solutionTargets)
                {
                    ProjectToBuild p1;
                    if (!projectsToBuildDict.TryGetValue(target.Name, out p1))
                    {
                        continue;
                    }
                    foreach (string dependency in target.DependsOnTargets.Split(';'))
                    {
                        ProjectToBuild p2;
                        if (!projectsToBuildDict.TryGetValue(dependency, out p2))
                        {
                            continue;
                        }
                        p1.dependencies.Add(p2);
                    }
                }
                return(true);
            }
Example #5
0
			/// <summary>
			/// Recursively increment requiredByCount on ptb and all its dependencies
			/// </summary>
			static void IncrementRequiredByCount(ProjectToBuild ptb)
			{
				if (ptb.visitFlag == 1) {
					return;
				}
				if (ptb.visitFlag == -1) {
					throw new DependencyCycleException();
				}
				ptb.visitFlag = -1;
				ptb.requiredByCount++;
				ptb.dependencies.ForEach(IncrementRequiredByCount);
				ptb.visitFlag = 1;
			}
Example #6
0
			/// <summary>
			/// Adds a ProjectToBuild item for the project and it's project references.
			/// Returns the added item, or null if an error occured.
			/// </summary>
			ProjectToBuild ParseMSBuildProject(IProject project)
			{
				ProjectToBuild ptb;
				if (parseMSBuildProjectProjectsToBuildDict.TryGetValue(project, out ptb)) {
					// only add each project once, reuse existing ProjectToBuild
					return ptb;
				}
				ptb = new ProjectToBuild(project.FileName, options.Target.TargetName);
				ptb.configuration = parentEngine.Configuration;
				ptb.platform = parentEngine.Platform;
				
				projectsToBuild.Add(ptb);
				parseMSBuildProjectProjectsToBuildDict[project] = ptb;
				
				foreach (ProjectItem item in project.GetItemsOfType(ItemType.ProjectReference)) {
					ProjectReferenceProjectItem prpi = item as ProjectReferenceProjectItem;
					if (prpi != null && prpi.ReferencedProject != null) {
						ProjectToBuild referencedProject = ParseMSBuildProject(prpi.ReferencedProject);
						if (referencedProject == null)
							return null;
						ptb.dependencies.Add(referencedProject);
					}
				}
				
				return ptb;
			}
Example #7
0
			bool ParseSolution(Project solution)
			{
				// get the build target to call
				Target mainBuildTarget = solution.Targets[options.Target.TargetName];
				if (mainBuildTarget == null) {
					currentResults.Result = BuildResultCode.BuildFileError;
					currentResults.Add(new BuildError(this.solution.FileName, "Target '" + options.Target + "' not supported by solution."));
					return false;
				}
				// example of mainBuildTarget:
				//  <Target Name="Build" Condition="'$(CurrentSolutionConfigurationContents)' != ''">
				//    <CallTarget Targets="Main\ICSharpCode_SharpDevelop;Main\ICSharpCode_Core;Main\StartUp;Tools" RunEachTargetSeparately="true" />
				//  </Target>
				List<BuildTask> mainBuildTargetTasks = Linq.ToList(Linq.CastTo<BuildTask>(mainBuildTarget));
				if (mainBuildTargetTasks.Count != 1
				    || mainBuildTargetTasks[0].Name != "CallTarget")
				{
					return InvalidTarget(mainBuildTarget);
				}
				
				List<Target> solutionTargets = new List<Target>();
				foreach (string solutionTargetName in mainBuildTargetTasks[0].GetParameterValue("Targets").Split(';'))
				{
					Target target = solution.Targets[solutionTargetName];
					if (target != null) {
						solutionTargets.Add(target);
					}
				}
				
				// dictionary for fast lookup of ProjectToBuild elements
				Dictionary<string, ProjectToBuild> projectsToBuildDict = new Dictionary<string, ProjectToBuild>();
				
				// now look through targets that took like this:
				//  <Target Name="Main\ICSharpCode_Core" Condition="'$(CurrentSolutionConfigurationContents)' != ''">
				//    <MSBuild Projects="Main\Core\Project\ICSharpCode.Core.csproj" Properties="Configuration=Debug; Platform=AnyCPU; BuildingSolutionFile=true; CurrentSolutionConfigurationContents=$(CurrentSolutionConfigurationContents); SolutionDir=$(SolutionDir); SolutionExt=$(SolutionExt); SolutionFileName=$(SolutionFileName); SolutionName=$(SolutionName); SolutionPath=$(SolutionPath)" Condition=" ('$(Configuration)' == 'Debug') and ('$(Platform)' == 'Any CPU') " />
				//    <MSBuild Projects="Main\Core\Project\ICSharpCode.Core.csproj" Properties="Configuration=Release; Platform=AnyCPU; BuildingSolutionFile=true; CurrentSolutionConfigurationContents=$(CurrentSolutionConfigurationContents); SolutionDir=$(SolutionDir); SolutionExt=$(SolutionExt); SolutionFileName=$(SolutionFileName); SolutionName=$(SolutionName); SolutionPath=$(SolutionPath)" Condition=" ('$(Configuration)' == 'Release') and ('$(Platform)' == 'Any CPU') " />
				//  </Target>
				// and add those targets to the "projectsToBuild" list.
				foreach (Target target in solutionTargets) {
					List<BuildTask> tasks = Linq.ToList(Linq.CastTo<BuildTask>(target));
					if (tasks.Count == 0) {
						return InvalidTarget(target);
					}
					
					// find task to run when this target is executed
					BuildTask bestTask = null;
					foreach (BuildTask task in tasks) {
						if (task.Name != "MSBuild") {
							return InvalidTarget(target);
						}
						if (MSBuildInternals.EvaluateCondition(solution, task.Condition)) {
							bestTask = task;
						}
					}
					if (bestTask == null) {
						LoggingService.Warn("No matching condition for solution target " + target.Name);
						bestTask = tasks[0];
					}
					
					// create projectToBuild entry and add it to list and dictionary
					string projectFileName = Path.Combine(this.solution.Directory, bestTask.GetParameterValue("Projects"));
					ProjectToBuild projectToBuild = new ProjectToBuild(Path.GetFullPath(projectFileName),
					                                                   bestTask.GetParameterValue("Targets"));
					
					// get project configuration and platform from properties section
					string propertiesString = bestTask.GetParameterValue("Properties");
					Match match = Regex.Match(propertiesString, @"\bConfiguration=([^;]+);");
					if (match.Success) {
						projectToBuild.configuration = match.Groups[1].Value;
					} else {
						projectToBuild.configuration = parentEngine.Configuration;
					}
					match = Regex.Match(propertiesString, @"\bPlatform=([^;]+);");
					if (match.Success) {
						projectToBuild.platform = match.Groups[1].Value;
					} else {
						projectToBuild.platform = parentEngine.Platform;
						if (projectToBuild.platform == "Any CPU") {
							projectToBuild.platform = "AnyCPU";
						}
					}
					
					projectsToBuild.Add(projectToBuild);
					projectsToBuildDict[target.Name] = projectToBuild;
				}
				
				// now create dependencies between projectsToBuild
				foreach (Target target in solutionTargets) {
					ProjectToBuild p1;
					if (!projectsToBuildDict.TryGetValue(target.Name, out p1))
						continue;
					foreach (string dependency in target.DependsOnTargets.Split(';')) {
						ProjectToBuild p2;
						if (!projectsToBuildDict.TryGetValue(dependency, out p2))
							continue;
						p1.dependencies.Add(p2);
					}
				}
				return true;
			}