Exemple #1
0
        public void ReportWarning(string message)
        {
            if (ReportGlobalDataToParent && parentMonitor != null)
            {
                parentMonitor.ReportWarning(message);
            }
            lock (warnings)
                warnings.Add(message);

            if (context != null)
            {
                context.Post((o) => OnWarningReported(message), null);
            }
            else
            {
                OnWarningReported(message);
            }

            if (followerMonitors != null)
            {
                foreach (var sm in followerMonitors)
                {
                    sm.ReportWarning(message);
                }
            }
        }
        public void ReportWarning(string message)
        {
            if (ReportGlobalDataToParent && parentMonitor != null)
            {
                parentMonitor.ReportWarning(message);
            }
            lock (warnings)
                warnings.Add(message);

            if (context != null)
            {
                context.Post((o) => {
                    var(mon, msg) = (ValueTuple <ProgressMonitor, string>)o;
                    mon.OnWarningReported(msg);
                }, (this, message));
            }
            else
            {
                OnWarningReported(message);
            }

            if (followerMonitors != null)
            {
                foreach (var sm in followerMonitors)
                {
                    sm.ReportWarning(message);
                }
            }
        }
		void InstallEntry (ProgressMonitor monitor, DeployContext ctx, SolutionFolderItem entry, ConfigurationSelector configuration)
		{
			foreach (DeployFile df in DeployService.GetDeployFiles (ctx, new SolutionFolderItem[] { entry }, configuration)) {
				string targetPath = df.ResolvedTargetFile;
				if (targetPath == null) {
					monitor.ReportWarning ("Could not copy file '" + df.RelativeTargetPath + "': Unknown target directory.");
					continue;
				}
				
				CopyFile (monitor, df.SourcePath, df.ResolvedTargetFile, df.FileAttributes);
			}
			
			SolutionFolder c = entry as SolutionFolder;
			if (c != null) {
				monitor.BeginTask ("Installing solution '" + c.Name + "'", c.Items.Count);
				foreach (SolutionFolderItem ce in c.Items) {
					InstallEntry (monitor, ctx, ce, configuration);
					monitor.Step (1);
				}
				monitor.EndTask ();
			}
		}
		internal void LoadSolution (Solution sol, SlnFile sln, ProgressMonitor monitor, SolutionLoadContext ctx)
		{
			var version = sln.FormatVersion;

			//Parse the .sln file
			var folder = sol.RootFolder;
			sol.Version = "0.1"; //FIXME:

			monitor.BeginTask("Loading projects ..", sln.Projects.Count + 1);
			Dictionary<string, SolutionFolderItem> items = new Dictionary<string, SolutionFolderItem> ();
			List<string> sortedList = new List<string> ();

			List<Task> loadTasks = new List<Task> ();

			foreach (SlnProject sec in sln.Projects) {
				try {
					// Valid guid?
					new Guid (sec.TypeGuid);
				} catch (FormatException) {
					monitor.Step (1);
					//Use default guid as projectGuid
					LoggingService.LogDebug (GettextCatalog.GetString (
						"Invalid Project type guid '{0}' on line #{1}. Ignoring.",
						sec.Id,
						sec.Line));
					continue;
				}

				string projTypeGuid = sec.TypeGuid.ToUpper ();
				string projectName = sec.Name;
				string projectPath = sec.FilePath;
				string projectGuid = sec.Id;

				lock (items)
					sortedList.Add (projectGuid);

				if (projTypeGuid == MSBuildProjectService.FolderTypeGuid) {
					//Solution folder
					SolutionFolder sfolder = new SolutionFolder ();
					sfolder.Name = projectName;
					sfolder.ItemId = projectGuid;

					DeserializeSolutionItem (monitor, sol, sfolder, sec);
					
					foreach (string f in ReadFolderFiles (sec))
						sfolder.Files.Add (MSBuildProjectService.FromMSBuildPath (Path.GetDirectoryName (sol.FileName), f));

					lock (items)
						items.Add (projectGuid, sfolder);

					monitor.Step (1);
					continue;
				}

				if (projectPath.StartsWith("http://")) {
					monitor.ReportWarning (GettextCatalog.GetString (
						"{0}({1}): Projects with non-local source (http://...) not supported. '{2}'.",
						sol.FileName, sec.Line, projectPath));
					monitor.Step (1);
					continue;
				}

				string path = MSBuildProjectService.FromMSBuildPath (Path.GetDirectoryName (sol.FileName), projectPath);
				if (String.IsNullOrEmpty (path)) {
					monitor.ReportWarning (GettextCatalog.GetString (
						"Invalid project path found in {0} : {1}", sol.FileName, projectPath));
					LoggingService.LogWarning (GettextCatalog.GetString (
						"Invalid project path found in {0} : {1}", sol.FileName, projectPath));
					monitor.Step (1);
					continue;
				}

				projectPath = Path.GetFullPath (path);
				
				SolutionItem item = null;
				Task<SolutionItem> loadTask;
				DateTime ti = DateTime.Now;

				if (sol.IsSolutionItemEnabled (projectPath)) {
					loadTask = Services.ProjectService.ReadSolutionItem (monitor, projectPath, format, projTypeGuid, projectGuid, ctx);
				} else {
					loadTask = Task.FromResult<SolutionItem> (new UnloadedSolutionItem () {
						FileName = projectPath
					});
				}

				var ft = loadTask.ContinueWith (ta => {
					try {
						item = ta.Result;
						if (item == null)
							throw new UnknownSolutionItemTypeException (projTypeGuid);
					} catch (Exception cex) {
						var e = UnwrapException (cex).First ();

						string unsupportedMessage = e.Message;

						if (e is UserException) {
							var ex = (UserException) e;
							LoggingService.LogError ("{0}: {1}", ex.Message, ex.Details);
							monitor.ReportError (string.Format ("{0}{1}{1}{2}", ex.Message, Environment.NewLine, ex.Details), null);
						} else {
							LoggingService.LogError (string.Format ("Error while trying to load the project {0}", projectPath), e);
							monitor.ReportWarning (GettextCatalog.GetString (
								"Error while trying to load the project '{0}': {1}", projectPath, e.Message));
						}

						SolutionItem uitem;
						uitem = new UnknownSolutionItem () {
							FileName = projectPath,
							LoadError = unsupportedMessage,
						};
						item = uitem;
						item.ItemId = projectGuid;
						item.TypeGuid = projTypeGuid;
					}

					item.UnresolvedProjectDependencies = ReadSolutionItemDependencies (sec);

					// Deserialize the object
					DeserializeSolutionItem (monitor, sol, item, sec);

					lock (items) {
						if (!items.ContainsKey (projectGuid)) {
							items.Add (projectGuid, item);
						} else {
							monitor.ReportError (GettextCatalog.GetString ("Invalid solution file. There are two projects with the same GUID. The project {0} will be ignored.", projectPath), null);
						}
					}
					monitor.Step (1);
				});
				loadTasks.Add (ft);
			}

			Task.WaitAll (loadTasks.ToArray ());

			sol.LoadedProjects = new HashSet<string> (items.Keys);

			var nested = sln.Sections.GetSection ("NestedProjects");
			if (nested != null)
				LoadNestedProjects (nested, items, monitor);

			// Resolve project dependencies
			foreach (var it in items.Values.OfType<SolutionItem> ()) {
				if (it.UnresolvedProjectDependencies != null) {
					foreach (var id in it.UnresolvedProjectDependencies.ToArray ()) {
						SolutionFolderItem dep;
						if (items.TryGetValue (id, out dep) && dep is SolutionItem) {
							it.UnresolvedProjectDependencies.Remove (id);
							it.ItemDependencies.Add ((SolutionItem)dep);
						}
					}
					if (it.UnresolvedProjectDependencies.Count == 0)
						it.UnresolvedProjectDependencies = null;
				}
			}

			//Add top level folders and projects to the main folder
			foreach (string id in sortedList) {
				SolutionFolderItem ce;
				if (items.TryGetValue (id, out ce) && ce.ParentFolder == null)
					folder.Items.Add (ce);
			}

			//FIXME: This can be just SolutionConfiguration also!
			LoadSolutionConfigurations (sln.SolutionConfigurationsSection, sol, monitor);

			LoadProjectConfigurationMappings (sln.ProjectConfigurationsSection, sol, items, monitor);

			foreach (var e in sln.Sections) {
				string name = e.Id;
				if (name.StartsWith ("MonoDevelopProperties.")) {
					int i = name.IndexOf ('.');
					LoadMonoDevelopConfigurationProperties (name.Substring (i+1), e, sol, monitor);
				}
			}

			monitor.EndTask ();
		}
		/// <summary>
		/// Validates the schema.
		/// </summary>		
		public static XmlSchema ValidateSchema (ProgressMonitor monitor, string xml, string fileName)
		{
			monitor.BeginTask (GettextCatalog.GetString ("Validating schema..."), 1);
			bool error = false;
			XmlSchema schema = null;
			try {
				StringReader stringReader = new StringReader (xml);
				XmlTextReader xmlReader = new XmlTextReader (stringReader);
				xmlReader.XmlResolver = null;
				
				ValidationEventHandler callback = delegate (object source, ValidationEventArgs args) {
					if (args.Severity == XmlSeverityType.Warning) {
						monitor.ReportWarning (args.Message);
					} else {
						monitor.ReportError (args.Message, args.Exception);
						error = true;
					}
					AddTask (fileName, args.Message, args.Exception.LinePosition, args.Exception.LineNumber,
					    (args.Severity == XmlSeverityType.Warning)? TaskSeverity.Warning : TaskSeverity.Error);
				};
				schema = XmlSchema.Read (xmlReader, callback);
				XmlSchemaSet sset = new XmlSchemaSet ();
				sset.Add (schema);
				sset.ValidationEventHandler += callback;
				sset.Compile ();
			} 
			catch (XmlSchemaException ex) {
				monitor.ReportError (ex.Message, ex);
				AddTask (fileName, ex.Message, ex.LinePosition, ex.LineNumber,TaskSeverity.Error);
				error = true;
			}
			catch (XmlException ex) {
				monitor.ReportError (ex.Message, ex);
				AddTask (fileName, ex.Message, ex.LinePosition, ex.LineNumber,TaskSeverity.Error);
				error = true;
			}
			
			if (error) {
				monitor.Log.WriteLine (GettextCatalog.GetString ("Validation failed."));
				TaskService.ShowErrors ();
			} else {
				monitor.Log.WriteLine  (GettextCatalog.GetString ("Schema is valid."));
			}
			
			monitor.EndTask ();
			return error? null: schema;
		}
		bool CopyFiles (ProgressMonitor monitor, IWorkspaceFileObject obj, IEnumerable<FilePath> files, FilePath targetBasePath, bool ignoreExternalFiles)
		{
			FilePath baseDir = obj.BaseDirectory.FullPath;
			foreach (FilePath file in files) {

				if (!File.Exists (file)) {
					monitor.ReportWarning (GettextCatalog.GetString ("File '{0}' not found.", file));
					continue;
				}
				FilePath fname = file.FullPath;
				
				// Can't export files from outside the root solution directory
				if (!fname.IsChildPathOf (baseDir)) {
					if (ignoreExternalFiles)
						continue;
					if (obj is Solution)
						monitor.ReportError (GettextCatalog.GetString ("The solution '{0}' is referencing the file '{1}' which is located outside the root solution directory.", obj.Name, Path.GetFileName (file)), null);
					else
						monitor.ReportError (GettextCatalog.GetString ("The project '{0}' is referencing the file '{1}' which is located outside the project directory.", obj.Name, Path.GetFileName (file)), null);
					return false;
				}

				FilePath rpath = fname.ToRelative (baseDir);
				rpath = rpath.ToAbsolute (targetBasePath);
				
				if (!Directory.Exists (rpath.ParentDirectory))
					Directory.CreateDirectory (rpath.ParentDirectory);

				File.Copy (file, rpath, true);
			}
			return true;
		}
		void CheckForPackageUpdates (
			ProgressMonitor progressMonitor,
			ProgressMonitorStatusMessage progressMessage,
			PackageUpdatesEventMonitor eventMonitor)
		{
			updatedPackagesInSolution.CheckForUpdates ();
			if (updatedPackagesInSolution.AnyUpdates ()) {
				progressMonitor.ReportSuccess (GettextCatalog.GetString ("Package updates are available."));
			} else if (eventMonitor.WarningReported) {
				progressMonitor.ReportWarning (progressMessage.Warning);
			} else {
				progressMonitor.ReportSuccess (progressMessage.Success);
			}
		}
		void EmitCustomCommandTargets (CustomCommandCollection commands, Project project, StringBuilder builder, string configName, CustomCommandType[] types, ProgressMonitor monitor)
		{
			bool warned = false;
			configName = configName.ToUpper ();
			foreach (CustomCommandType type in types) {
				bool targetEmitted = false;
				for (int i = 0; i < commands.Count; i ++) {
					CustomCommand cmd = commands [i];
					if (cmd.Type != type) {
						if (!warned && Array.IndexOf (types, cmd.Type) < 0) {
							//Warn (only once) if unsupported custom command is found,
							StringBuilder types_list = new StringBuilder ();
							foreach (CustomCommandType t in types)
								types_list.AppendFormat ("{0}, ", t);
							monitor.ReportWarning (GettextCatalog.GetString (
								"Custom commands of only the following types are supported: {0}.", types_list.ToString ()));
							warned = true;
						}
						continue;
					}

					if (!targetEmitted) {
						builder.AppendFormat ("{0}_{1}:\n", configName, type.ToString ());
						targetEmitted = true;
					}

					string dir, exe, args;
					ResolveCustomCommand (project, cmd, out dir, out exe, out args);
					builder.AppendFormat ("\t(cd {0} && {1} {2})\n", dir, exe, args);
				}
				if (targetEmitted)
					builder.Append ("\n");
			}
		}
		void CleanDone (ProgressMonitor monitor, BuildResult result, IBuildTarget entry, ITimeTracker tt)
		{
			tt.Trace ("Begin reporting clean result");
			try {
				if (result != null) {
					monitor.Log.WriteLine ();
					monitor.Log.WriteLine (GettextCatalog.GetString ("---------------------- Done ----------------------"));

					tt.Trace ("Updating task service");
				
					ReportErrors (result);

					tt.Trace ("Reporting result");

					string errorString = GettextCatalog.GetPluralString ("{0} error", "{0} errors", result.ErrorCount, result.ErrorCount);
					string warningString = GettextCatalog.GetPluralString ("{0} warning", "{0} warnings", result.WarningCount, result.WarningCount);

					if (monitor.CancellationToken.IsCancellationRequested) {
						monitor.ReportError (GettextCatalog.GetString ("Clean canceled."), null);
					} else if (result.ErrorCount == 0 && result.WarningCount == 0 && result.FailedBuildCount == 0) {
						monitor.ReportSuccess (GettextCatalog.GetString ("Clean successful."));
					} else if (result.ErrorCount == 0 && result.WarningCount > 0) {
						monitor.ReportWarning (GettextCatalog.GetString ("Clean: ") + errorString + ", " + warningString);
					} else if (result.ErrorCount > 0) {
						monitor.ReportError (GettextCatalog.GetString ("Clean: ") + errorString + ", " + warningString, null);
					} else {
						monitor.ReportError (GettextCatalog.GetString ("Clean failed."), null);
					}
				}

				OnEndClean (monitor, tt);

				tt.Trace ("Showing results pad");

				ShowErrorsPadIfNecessary ();

			} finally {
				monitor.Dispose ();
				tt.End ();
			}
		}
		public virtual void UpdateCatalog (TranslationProject project, Catalog catalog, ProgressMonitor monitor, string fileName)
		{
			string text = File.ReadAllText (fileName);
			string relativeFileName = MonoDevelop.Core.FileService.AbsoluteToRelativePath (project.BaseDirectory, fileName);
			string fileNamePrefix   = relativeFileName + ":";
			if (String.IsNullOrEmpty (text))
				return;
			
			// Get a list of all excluded regions
			List<Match> excludeMatches = new List<Match> ();
			foreach (Regex regex in excluded) {
				foreach (Match m in regex.Matches (text))
					excludeMatches.Add (m);
			}
			
			// Sort the list by match index
			excludeMatches.Sort (delegate (Match a, Match b) {
				return a.Index.CompareTo (b.Index);
			});
			
			// Remove from the list all regions which start in an excluded region
			int pos=0;
			for (int n=0; n<excludeMatches.Count; n++) {
				Match m = excludeMatches [n];
				if (m.Index < pos) {
					excludeMatches.RemoveAt (n);
					n--;
				} else {
					pos = m.Index + m.Length;
				}
			}
			
			foreach (RegexInfo ri in regexes) {
				int lineNumber = 0;
				int oldIndex  = 0;
				foreach (Match match in ri.Regex.Matches (text)) {
					// Ignore matches inside excluded regions
					bool ignore = false;
					foreach (Match em in excludeMatches) {
						if (match.Index >= em.Index && match.Index < em.Index + em.Length) {
							ignore = true;
							LoggingService.LogDebug ("Excluded Gettext string '{0}' in file '{1}'", match.Groups[ri.ValueGroupIndex].Value, fileName);
							break;
						}
					}
					if (ignore)
						continue;
					
					string mt = match.Groups[ri.ValueGroupIndex].Value;
					if (mt.Length == 0)
						continue;
					
					foreach (TransformInfo ti in transforms)
						mt = ti.Regex.Replace (mt, ti.ReplaceText);
					
					try {
						mt = StringEscaping.UnEscape (ri.EscapeMode, mt);
					} catch (FormatException fex) {
						monitor.ReportWarning ("Error unescaping string '" + mt + "': " + fex.Message);
						continue;
					}
					
					if (mt.Trim().Length == 0)
						continue;
					
					//get the plural string if it's a plural form and apply transforms
					string pt = ri.PluralGroupIndex != -1 ? match.Groups[ri.PluralGroupIndex].Value : null;
					if (pt != null)
						foreach (TransformInfo ti in transforms)
							pt = ti.Regex.Replace (pt, ti.ReplaceText);
					
					//add to the catalog
					CatalogEntry entry = catalog.AddItem (mt, pt);
					lineNumber += GetLineCount (text, oldIndex, match.Index);
					oldIndex = match.Index;
					entry.AddReference (fileNamePrefix + lineNumber);
				}
			}
		}
		async Task<BuildResult> OnBuild (ProgressMonitor monitor, ConfigurationSelector configuration)
		{
			if (!project.OnGetNeedsBuilding (configuration)) {
				monitor.Log.WriteLine (GettextCatalog.GetString ("Skipping project since output files are up to date"));
				return new BuildResult ();
			}

			if (!project.TargetRuntime.IsInstalled (project.TargetFramework)) {
				BuildResult res = new BuildResult ();
				res.AddError (GettextCatalog.GetString ("Framework '{0}' not installed.", project.TargetFramework.Name));
				return res;
			}
			
			bool hasBuildableFiles = false;
			foreach (ProjectFile pf in project.Files) {
				if (pf.BuildAction == BuildAction.Compile || pf.BuildAction == BuildAction.EmbeddedResource) {
					hasBuildableFiles = true;
					break;
				}
			}
			if (!hasBuildableFiles)
				return new BuildResult ();
			
			if (project.LanguageBinding == null) {
				BuildResult langres = new BuildResult ();
				string msg = GettextCatalog.GetString ("Unknown language '{0}'. You may need to install an additional add-in to support this language.", project.LanguageName);
				langres.AddError (msg);
				monitor.ReportError (msg, null);
				return langres;
			}

			BuildResult refres = null;
			HashSet<ProjectItem> itemsToExclude = new HashSet<ProjectItem> ();
			
			foreach (ProjectReference pr in project.References) {
				
				if (pr.ReferenceType == ReferenceType.Project) {
					// Ignore non-dotnet projects
					Project p = project.ParentSolution != null ? pr.ResolveProject (project.ParentSolution) : null;
					if (p != null && !(p is DotNetProject))
						continue;

					if (p == null || pr.GetReferencedFileNames (configuration).Length == 0) {
						if (refres == null)
							refres = new BuildResult ();
						string msg = GettextCatalog.GetString ("Referenced project '{0}' not found in the solution.", pr.Reference);
						monitor.ReportWarning (msg);
						refres.AddWarning (msg);
					}
				}
				
				if (!pr.IsValid) {
					if (refres == null)
						refres = new BuildResult ();
					string msg;
					if (!pr.IsExactVersion && pr.SpecificVersion) {
						msg = GettextCatalog.GetString ("Reference '{0}' not found on system. Using '{1}' instead.", pr.StoredReference, pr.Reference);
						monitor.ReportWarning (msg);
						refres.AddWarning (msg);
					}
					else {
						bool errorsFound = false;
						foreach (string asm in pr.GetReferencedFileNames (configuration)) {
							if (!File.Exists (asm)) {
								msg = GettextCatalog.GetString ("Assembly '{0}' not found. Make sure that the assembly exists in disk. If the reference is required to build the project you may get compilation errors.", Path.GetFileName (asm));
								refres.AddWarning (msg);
								monitor.ReportWarning (msg);
								errorsFound = true;
								itemsToExclude.Add (pr);
							}
						}
						msg = null;
						if (!errorsFound) {
							msg = GettextCatalog.GetString ("The reference '{0}' is not valid for the target framework of the project.", pr.StoredReference, pr.Reference);
							monitor.ReportWarning (msg);
							refres.AddWarning (msg);
							itemsToExclude.Add (pr);
						}
					}
				}
			}
			
			DotNetProjectConfiguration conf = (DotNetProjectConfiguration) project.GetConfiguration (configuration);

			// Create a copy of the data needed to compile the project.
			// This data can be modified by extensions.
			// Also filter out items whose condition evaluates to false
			
			BuildData buildData = new BuildData ();
			ProjectParserContext ctx = new ProjectParserContext (project, conf);
		
			buildData.Items = new ProjectItemCollection ();
			foreach (ProjectItem item in project.Items) {
				if (!itemsToExclude.Contains (item) && (string.IsNullOrEmpty (item.Condition) || ConditionParser.ParseAndEvaluate (item.Condition, ctx)))
					buildData.Items.Add (item);
			}
			buildData.Configuration = (DotNetProjectConfiguration) project.CloneConfiguration (conf, conf.Id);
			buildData.Configuration.SetParentItem (project);
			buildData.ConfigurationSelector = configuration;

			var br = await project.Compile (monitor, buildData);

			if (refres != null) {
				refres.Append (br);
				return refres;
			} else
				return br;
		}
		//use events.. 
		public void UpdateProject (ProgressMonitor monitor, bool promptForRemoval)
		{
			if (!IntegrationEnabled)
				return;

			if (ownerProject == null)
				throw new InvalidOperationException ("Internal Error: ownerProject not set");

			this.monitor = monitor;

			try {
				Makefile.GetVariables ();
			} catch (Exception e) {
				monitor.ReportError (GettextCatalog.GetString (
					"Invalid Makefile '{0}'. Disabling Makefile integration.", AbsoluteMakefileName), e);
				IntegrationEnabled = false;

				return;
			}

			//FIXME: Improve the message
			if (promptForRemoval) {
				AlertButton projectButton = new AlertButton ("_Project");
				AlertButton makefileButton = new AlertButton ("_Makefile");
				AlertButton choice = MessageService.AskQuestion (GettextCatalog.GetString ("Enabling Makefile integration. You can choose to have either the Project or the Makefile be used as the master copy. This is done only when enabling this feature. After this, the Makefile will be taken as the master copy."),
				                                                 projectButton, makefileButton);
				if (choice == projectButton) {
					//Sync Project --> Makefile
					dirty = true;
					return;
				}
			}

			dirty = true;
			encodeValues = null;

			try {
				if (IsAutotoolsProject) {
					string path = Path.Combine (AbsoluteConfigureInPath, "configure.in");
					if (!File.Exists (path))
						path = Path.Combine (AbsoluteConfigureInPath, "configure.ac");
					
					configuredPackages = null;
					WeakReference weakref;
					if (PkgManagerTable.TryGetValue (path, out weakref)) {
						if (weakref.IsAlive) {
							configuredPackages = (ConfiguredPackagesManager) weakref.Target;
							FileInfo finfo = new FileInfo (path);
							if (finfo.LastWriteTime > configuredPackages.LastWriteTime)
								// file has changed since last time we parsed it!
								configuredPackages = null;
						}
					}

					// no entry in table or it got collected or file has changed
					if (configuredPackages == null) {
						configuredPackages = new ConfiguredPackagesManager (path);
						PkgManagerTable [path] = new WeakReference (configuredPackages);
						ownerProject.ExtendedProperties ["MonoDevelop.Autotools.ConfiguredPackagesManager"] = configuredPackages;
					}
				}
			} catch (Exception e) {
				LoggingService.LogWarning (
					"Error trying to read configure.in ('{0}') for project '{1}':\n{2}",
					AbsoluteConfigureInPath, OwnerProject.Name, e.ToString ());

				monitor.ReportWarning (GettextCatalog.GetString (
					"Error trying to read configure.in ('{0}') for project '{1}':\n{2}",
					AbsoluteConfigureInPath, OwnerProject.Name, e.Message));
			}

			ReadFiles (BuildFilesVar, BuildAction.Compile, "Build", promptForRemoval);
			ReadFiles (DeployFilesVar, BuildAction.Content, "Deploy", promptForRemoval);
			ReadFiles (OthersVar, BuildAction.None, "Others", promptForRemoval);
			ReadFiles (ResourcesVar, BuildAction.EmbeddedResource, "Resources", promptForRemoval);

			if (!SyncReferences)
				return;

			try {
				SaveReferences = true;

				//Do these for DotNetProject only
				DotNetProject dotnetProject = ownerProject as DotNetProject;
				if (dotnetProject != null) {
					PackageRefVar.Extra.Clear ();
					AsmRefVar.Extra.Clear ();
					ProjectRefVar.Extra.Clear ();

					existingPackageRefs = new Dictionary<string, ProjectReference> ();
					requiredPackageVersions = new Dictionary<string,string> ();
					newPackageRefs = new Dictionary<string, ProjectReference> ();

					List<ProjectReference> toRemove = new List<ProjectReference> ();
					foreach (ProjectReference pref in dotnetProject.References) {
						if (pref.ReferenceType == ReferenceType.Package) {
							string [] files = pref.GetReferencedFileNames (ConfigurationSelector.Default);
							if (files == null)
								continue;

							if (pref.ReferenceType == ReferenceType.Package) {
								// Store the package version required by this reference. We'll use
								// the same version when trying to match references coming from the makefile
								SystemAssembly asm = assemblyContext.GetAssemblyFromFullName (pref.StoredReference, pref.Package != null ? pref.Package.Name : null, dotnetProject.TargetFramework);
								if (asm != null && asm.Package != null)
									requiredPackageVersions [asm.Package.Name] = asm.Package.Version;
							}
							// this should help normalize paths like /foo//bar/../
							string fullpath = Path.GetFullPath (files [0]);
							if (existingPackageRefs.ContainsKey (fullpath))
								toRemove.Add (pref);
							else
								existingPackageRefs [fullpath] = pref;
						}
					}

					// Remove the repeats
					foreach (ProjectReference pref in toRemove)
						dotnetProject.References.Remove (pref);

					ReadReferences (PackageRefVar, ReferenceType.Package, "Package References", dotnetProject);

					// !SaveReferences indicates that previous ref reading failed
					if (SaveReferences && String.Compare (AsmRefVar.Name, PackageRefVar.Name) != 0)
						ReadReferences (AsmRefVar, ReferenceType.Assembly, "Asm References", dotnetProject);
					if (SaveReferences && (String.Compare (ProjectRefVar.Name, PackageRefVar.Name) != 0) && 
						(String.Compare (ProjectRefVar.Name, AsmRefVar.Name) != 0))
						ReadReferences (ProjectRefVar, ReferenceType.Project, "Project References", dotnetProject);
					
					//Resolve References
					//Required when UpdateProject gets called by ui
					if (ownerProject.ParentSolution != null)
						ResolveProjectReferences (ownerProject.ParentSolution.RootFolder, monitor);
					
					//only remove unmatched existing refs if everything resolved without errors
					if (SaveReferences) {
						foreach (ProjectReference pr in existingPackageRefs.Values)
							dotnetProject.References.Remove (pr);
					}

					existingPackageRefs.Clear ();
					newPackageRefs.Clear ();
				}
			} catch (Exception e) {
				string msg = GettextCatalog.GetString (
					"Error in loading references: {0}. Skipping syncing of references", e.Message);
				LoggingService.LogWarning (msg);
				monitor.ReportWarning (msg);

				SaveReferences = false;
			}

			this.monitor = null;
		}
		public Makefile Deploy (AutotoolsContext ctx, SolutionFolderItem entry, ProgressMonitor monitor)
		{
			generateAutotools = ctx.MakefileType == MakefileType.AutotoolsMakefile;
			
			monitor.BeginTask ( GettextCatalog.GetString (
						"Creating {0} for Project {1}",
						generateAutotools ? "Makefile.am" : "Makefile", entry.Name), 1 );
			
			Makefile makefile = new Makefile ();
			try
			{
				if ( !CanDeploy (entry, generateAutotools ? MakefileType.AutotoolsMakefile : MakefileType.SimpleMakefile) ) 
					throw new Exception ( GettextCatalog.GetString ("Not a deployable project.") );

				Project project = entry as Project;
				TemplateEngine templateEngine = new TemplateEngine();			
				ISimpleAutotoolsSetup setup = FindSetupForProject ( project );

				// Handle files to be deployed
				deployDirs = new Dictionary<string, StringBuilder> ();
				deployFileVars = new Dictionary<string, string> ();
				builtFiles = new List<string> ();
				deployFileCopyVars = new StringBuilder ();
				deployFileCopyTargets = new StringBuilder ();

				//used only for simple makefile generation
				templateFilesTargets = null;
				installTarget = null;
				installDeps = null;
				installDirs = null;
				uninstallTarget = null;

				// handle configuration specific variables
				conf_vars = new StringBuilder ();

				// grab all project files
				files = new StringBuilder ();
				res_files = new StringBuilder ();
				extras = new StringBuilder ();
				datafiles = new StringBuilder ();
				Set<string> extraFiles = new Set<string> ();

				string includes = String.Empty;
				string references, dllReferences;
				DotNetProject netProject = project as DotNetProject;
				ProcessProjectReferences (netProject, out references, out dllReferences, ctx);

				templateEngine.Variables["REFERENCES"] = references;
				templateEngine.Variables["DLL_REFERENCES"] =  dllReferences;
				templateEngine.Variables["WARNING"] = "Warning: This is an automatically generated file, do not edit!";

				DotNetProject dotnetProject = entry as DotNetProject;
				if (dotnetProject != null)
				{
					string resgen = "resgen";
					if (System.Environment.Version.Major >= 2) {
						switch (dotnetProject.TargetFramework.ClrVersion) {
							case ClrVersion.Net_1_1: resgen = "resgen1"; break;
							default: resgen = "resgen2"; break;
						}
					}
					templateEngine.Variables ["RESGEN"] = resgen;
				}
				
				string pfpath = null;
				foreach (ProjectFile projectFile in project.Files) 
				{
					pfpath = FileService.NormalizeRelativePath (projectFile.FilePath.ToRelative (project.BaseDirectory));
					switch ( projectFile.BuildAction )
					{
						case BuildAction.Compile:
							
							if ( projectFile.Subtype != Subtype.Code ) continue;
							files.AppendFormat ( "\\\n\t{0} ", MakefileData.ToMakefilePath (pfpath));
							break;

						case BuildAction.Content:
						case BuildAction.None:

							extraFiles.Add (MakefileData.ToMakefilePath (pfpath));
							break;

						case BuildAction.EmbeddedResource:

							if ( !projectFile.FilePath.IsChildPathOf ( ctx.BaseDirectory ) )
							{
								// file is not within directory hierarchy, copy it in
								string rdir = Path.Combine (Path.GetDirectoryName (project.FileName), resourcedir);
								if ( !Directory.Exists ( rdir ) ) Directory.CreateDirectory ( rdir );
								string newPath = Path.Combine (rdir, Path.GetFileName ( projectFile.FilePath ));
								FileService.CopyFile ( projectFile.FilePath, newPath ) ;
								pfpath = project.GetRelativeChildPath (newPath);
								pfpath = FileService.NormalizeRelativePath (pfpath);
							}
							if (!String.IsNullOrEmpty (projectFile.ResourceId) && projectFile.ResourceId != Path.GetFileName (pfpath))
								res_files.AppendFormat ("\\\n\t{0},{1} ", MakefileData.ToMakefilePath (pfpath), MakefileData.EscapeString (projectFile.ResourceId));
							else
								res_files.AppendFormat ("\\\n\t{0} ", MakefileData.ToMakefilePath (pfpath));
 
							break;

						case "FileCopy":

							datafiles.AppendFormat ("\\\n\t{0} ", MakefileData.ToMakefilePath (pfpath));
							break;
					}
				}

				if (!generateAutotools) {
					templateFilesTargets = new StringBuilder ();
					installTarget = new StringBuilder ();
					uninstallTarget = new StringBuilder ();
					installDeps = new StringBuilder ();
					installDirs = new List<string> ();

					customCommands = new StringBuilder ();

					string programFilesDir = ctx.DeployContext.GetDirectory (TargetDirectory.ProgramFiles);
					//FIXME:temp
					programFilesDir = TranslateDir (programFilesDir);
					installDirs.Add (programFilesDir);
					installTarget.Append ("\tmake pre-install-local-hook prefix=$(prefix)\n");
					installTarget.Append ("\tmake install-satellite-assemblies prefix=$(prefix)\n");
					installTarget.AppendFormat ("\tmkdir -p '$(DESTDIR){0}'\n", programFilesDir);
					installTarget.AppendFormat ("\t$(call cp,$(ASSEMBLY),$(DESTDIR){0})\n", programFilesDir);
					installTarget.AppendFormat ("\t$(call cp,$(ASSEMBLY_MDB),$(DESTDIR){0})\n", programFilesDir);

					//remove dir?
					uninstallTarget.Append ("\tmake pre-uninstall-local-hook prefix=$(prefix)\n");
					uninstallTarget.Append ("\tmake uninstall-satellite-assemblies prefix=$(prefix)\n");
					uninstallTarget.AppendFormat ("\t$(call rm,$(ASSEMBLY),$(DESTDIR){0})\n", programFilesDir);
					uninstallTarget.AppendFormat ("\t$(call rm,$(ASSEMBLY_MDB),$(DESTDIR){0})\n", programFilesDir);

					installDeps.Append (" $(ASSEMBLY) $(ASSEMBLY_MDB)");

					conf_vars.AppendFormat ("srcdir=.\n");
					conf_vars.AppendFormat ("top_srcdir={0}\n\n",
						FileService.AbsoluteToRelativePath (project.BaseDirectory, ctx.TargetSolution.BaseDirectory));

					conf_vars.AppendFormat ("include $(top_srcdir)/config.make\n\n");

					// Don't emit for top level project makefile(eg. pdn.make), as it would be
					// included by top level solution makefile
					if (ctx.TargetSolution.BaseDirectory != project.BaseDirectory){
						string customhooks = Path.Combine (project.BaseDirectory, "custom-hooks.make");
						bool include = File.Exists (customhooks);
					
						includes = "include $(top_srcdir)/Makefile.include\n";
						includes += String.Format ("{0}include $(srcdir)/custom-hooks.make\n\n", include ? "" : "#");
						if (include)
							makefile.SetVariable ("EXTRA_DIST", "$(srcdir)/custom-hooks.make");
					}
				}

				bool buildEnabled;
				List<ConfigSection> configSections = new List<ConfigSection> ();
				allDeployVars = new Dictionary<string, DeployFileData> ();

				foreach (SolutionConfiguration combineConfig in ctx.TargetSolution.Configurations)
				{
					DotNetProjectConfiguration config = GetProjectConfig (combineConfig.Id, project, out buildEnabled) as DotNetProjectConfiguration;
					if (config == null)
						continue;

					ConfigSection configSection = new ConfigSection (combineConfig.Id);

					string assembly = MakefileData.GetUnixPath (project.GetRelativeChildPath (config.CompiledOutputName));

					configSection.BuildVariablesBuilder.AppendFormat ("ASSEMBLY_COMPILER_COMMAND = {0}\n",
							setup.GetCompilerCommand ( project, config.Id ) );
					configSection.BuildVariablesBuilder.AppendFormat ("ASSEMBLY_COMPILER_FLAGS = {0}\n",
							setup.GetCompilerFlags ( project, config.Id ) );

					// add check for compiler command in configure.ac
					ctx.AddCommandCheck ( setup.GetCompilerCommand ( project, config.Id ) );

					configSection.BuildVariablesBuilder.AppendFormat ("ASSEMBLY = {0}\n",
						AutotoolsContext.EscapeStringForAutomake (assembly));
					configSection.BuildVariablesBuilder.AppendFormat ("ASSEMBLY_MDB = {0}\n",
						config.DebugSymbols ? "$(ASSEMBLY).mdb" : String.Empty);

					string target;
					switch (config.CompileTarget)
					{
						case CompileTarget.Exe:
							target = "exe";
							break;
						case CompileTarget.Library:
							target = "library";
							break;
						case CompileTarget.WinExe:
							target = "winexe";
							break;
						case CompileTarget.Module:
							target = "module";
							break;
						default:
							throw new Exception( GettextCatalog.GetString ("Unknown target {0}", config.CompileTarget ) );
					}
					configSection.BuildVariablesBuilder.AppendFormat ( "COMPILE_TARGET = {0}\n", target );

					// for project references, we need a ref to the dll for the current configuration
					StringWriter projectReferences = new StringWriter();
					string pref = null;
					foreach (ProjectReference reference in netProject.References) 
					{
						if (reference.ReferenceType != ReferenceType.Project)
							continue;
						Project refp = reference.ResolveProject (ctx.TargetSolution);
						if (refp == null) {
							throw new Exception (GettextCatalog.GetString ("Couldn't find referenced project '{0}'", reference.Reference));
						}
						if (!(refp is DotNetProject))
							continue;
						
						DotNetProjectConfiguration dnpc = GetProjectConfig (combineConfig.Id, refp, out buildEnabled) as DotNetProjectConfiguration;
						if ( dnpc == null )
							throw new Exception ( GettextCatalog.GetString
									("Could not add reference to project '{0}'", refp.Name) );

						projectReferences.WriteLine (" \\");
						projectReferences.Write ("\t");
						pref = project.GetRelativeChildPath (dnpc.CompiledOutputName);

						projectReferences.Write (MakefileData.ToMakefilePath (pref));
					}
					configSection.BuildVariablesBuilder.AppendFormat ( "PROJECT_REFERENCES = {0}\n", projectReferences.ToString() );

					string buildDir = project.GetRelativeChildPath (config.OutputDirectory);
					configSection.BuildVariablesBuilder.AppendFormat ("BUILD_DIR = {0}\n", MakefileData.ToMakefilePath (buildDir));

					// Register files built by this configuration.
					// Built files won't be distributed.
					foreach (string bfile in builtFiles)
						ctx.AddBuiltFile (Path.Combine (config.OutputDirectory, bfile));

					DeployFileCollection deployFiles = DeployService.GetDeployFiles (
							ctx.DeployContext, new SolutionFolderItem[] { project }, config.Selector);

					ProcessDeployFilesForConfig (deployFiles, project, configSection, ctx, config);
					configSections.Add (configSection);

					if (!generateAutotools) {
						EmitCustomCommandTargets (config.CustomCommands, project, customCommands, combineConfig.Id,
								new CustomCommandType [] {
									CustomCommandType.BeforeBuild,
									CustomCommandType.AfterBuild,
									CustomCommandType.BeforeClean,
									CustomCommandType.AfterClean}, monitor);
					} else {
						if (config.CustomCommands.Count > 0)
							monitor.ReportWarning (GettextCatalog.GetString ("Custom commands are not supported for autotools based makefiles. Ignoring."));
					}

					// Register files generated by the compiler
					ctx.AddBuiltFile (project.GetOutputFileName (combineConfig.Selector));
					if (config.DebugSymbols)
						ctx.AddBuiltFile (project.GetOutputFileName (combineConfig.Selector) + ".mdb");

					if (config.SignAssembly) {
						string spath = project.GetRelativeChildPath (config.AssemblyKeyFile);
						spath = FileService.NormalizeRelativePath (spath);
						extraFiles.Add (MakefileData.ToMakefilePath (spath));
					}

					if (buildEnabled && pkgs.Count > 0)
						ctx.AddRequiredPackages (combineConfig.Id, pkgs);
				}


				foreach (string ef in extraFiles)
					extras.AppendFormat ("\\\n\t{0} ", ef);

				Dictionary<string, DeployFileData> commonDeployVars = new Dictionary<string, DeployFileData> (allDeployVars);
				foreach (ConfigSection configSection in configSections) {
					List<string> toRemove = new List<string> ();
					foreach (KeyValuePair<string, DeployFileData> pair in commonDeployVars) {
						if (!configSection.DeployFileVars.ContainsKey (pair.Key))
							toRemove.Add (pair.Key);
					}
					foreach (string s in toRemove)
						commonDeployVars.Remove (s);
				}

				//emit the config sections here.. to conf_vars
				foreach (ConfigSection configSection in configSections) {
					conf_vars.AppendFormat (generateAutotools ? "if ENABLE_{0}\n" : "ifeq ($(CONFIG),{0})\n",
							ctx.EscapeAndUpperConfigName (configSection.Name));

					conf_vars.Append (configSection.BuildVariablesBuilder.ToString ());
					conf_vars.Append ("\n");
					
					if (ctx.Switches != null) {
						foreach (Switch s in ctx.Switches) {
							conf_vars.AppendLine (string.Format (@"if ENABLE_{0}
ASSEMBLY_COMPILER_FLAGS += -define:{1}
endif", s.SwitchName.Replace ('-', '_').ToUpperInvariant (), s.Define));
						}
					}

					foreach (KeyValuePair<string, DeployFileData> pair in allDeployVars) {
						string targetDeployVar = pair.Key;
						if (pair.Value.File.ContainsPathReferences)
							//Template files are not handled per-config
							continue;

						if (configSection.DeployFileVars.ContainsKey (targetDeployVar)) {
							//use the dfile from the config section
							DeployFile dfile = configSection.DeployFileVars [targetDeployVar];
							string fname = MakefileData.ToMakefilePath (
									FileService.AbsoluteToRelativePath (
										Path.GetFullPath (project.BaseDirectory),
										Path.GetFullPath (dfile.SourcePath)));

							conf_vars.AppendFormat ("{0}_SOURCE={1}\n", targetDeployVar, fname);

							if (!commonDeployVars.ContainsKey (targetDeployVar)) {
								//FOO_DLL=$(BUILD_DIR)/foo.dll
								conf_vars.AppendFormat ("{0}=$(BUILD_DIR)/{1}\n",
										targetDeployVar,
										MakefileData.ToMakefilePath (dfile.RelativeTargetPath));
							}
						} else {
							// not common and not part of @configSection
							conf_vars.AppendFormat ("{0}=\n", pair.Key);
						}
					}

					conf_vars.Append ( "\nendif\n\n" );
				}

				conf_vars.AppendFormat ("AL={0}\n", (dotnetProject.TargetFramework.ClrVersion == ClrVersion.Net_2_0) ? "al2" : "al");
				conf_vars.AppendFormat ("SATELLITE_ASSEMBLY_NAME=$(notdir $(basename $(ASSEMBLY))).resources.dll\n");

				foreach (KeyValuePair<string, DeployFileData> pair in allDeployVars) {
					HandleDeployFile (pair.Value, pair.Key, project, ctx);

					if (commonDeployVars.ContainsKey (pair.Key)) {
						//FOO_DLL=$(BUILD_DIR)/foo.dll
						deployFileCopyVars.AppendFormat ("{0} = $(BUILD_DIR)/{1}\n",
									pair.Key,
									MakefileData.ToMakefilePath (pair.Value.File.RelativeTargetPath));
					}
				}
				
				conf_vars.Append ('\n');
				
				StringBuilder vars = new StringBuilder ();
				foreach (KeyValuePair<string, StringBuilder> pair in deployDirs) {
					//PROGRAM_FILES= .. etc
					conf_vars.AppendFormat ("{0} = {1} \n\n", pair.Key, pair.Value.ToString ());
					//Build list of deploy dir variables
					vars.AppendFormat ("$({0}) ", pair.Key);
				}

				if (!generateAutotools) {
					installTarget.Insert (0, String.Format ("install-local:{0}\n", installDeps.ToString ()));
					installTarget.Append ("\tmake post-install-local-hook prefix=$(prefix)\n");

					uninstallTarget.Insert (0, String.Format ("uninstall-local:{0}\n", installDeps.ToString ()));
					uninstallTarget.Append ("\tmake post-uninstall-local-hook prefix=$(prefix)\n");
				}

				if (!generateAutotools && customCommands.Length > 0)
					customCommands.Insert (0, "# Targets for Custom commands\n");

				templateEngine.Variables["CONFIG_VARS"] = conf_vars.ToString ();
				templateEngine.Variables["DEPLOY_FILE_VARS"] = vars.ToString ();
				templateEngine.Variables["COPY_DEPLOY_FILES_VARS"] = deployFileCopyVars.ToString();
				templateEngine.Variables["COPY_DEPLOY_FILES_TARGETS"] = deployFileCopyTargets.ToString();
				templateEngine.Variables["ALL_TARGET"] = (ctx.TargetSolution.BaseDirectory == project.BaseDirectory) ? "all-local" : "all";
				templateEngine.Variables["INCLUDES"] = includes;

				templateEngine.Variables["FILES"] = files.ToString();
				templateEngine.Variables["RESOURCES"] = res_files.ToString();
				templateEngine.Variables["EXTRAS"] = extras.ToString();
				templateEngine.Variables["DATA_FILES"] = datafiles.ToString();
				templateEngine.Variables["CLEANFILES"] = vars.ToString ();

				if (!generateAutotools) {
					templateEngine.Variables["TEMPLATE_FILES_TARGETS"] = templateFilesTargets.ToString();
					templateEngine.Variables["INSTALL_TARGET"] = installTarget.ToString();
					templateEngine.Variables["UNINSTALL_TARGET"] = uninstallTarget.ToString();
					templateEngine.Variables["CUSTOM_COMMAND_TARGETS"] = customCommands.ToString();
				}

				// Create project specific makefile
				Stream stream = ctx.GetTemplateStream (
						generateAutotools ? "Makefile.am.project.template" : "Makefile.noauto.project.template");

				StreamReader reader = new StreamReader (stream);
				string txt = templateEngine.Process ( reader );
				reader.Close();

				makefile.Append ( txt );
				monitor.Step (1);
			}
			finally	{ monitor.EndTask (); }
			return makefile;
		}
		void BuildDone (ProgressMonitor monitor, BuildResult result, IBuildTarget entry, ITimeTracker tt)
		{
			TaskListEntry[] tasks = null;
			tt.Trace ("Begin reporting build result");
			try {
				if (result != null) {
					lastResult = result;
					monitor.Log.WriteLine ();
					monitor.Log.WriteLine (GettextCatalog.GetString ("---------------------- Done ----------------------"));
					
					tt.Trace ("Updating task service");
					tasks = new TaskListEntry [result.Errors.Count];
					for (int n=0; n<tasks.Length; n++) {
						tasks [n] = new TaskListEntry (result.Errors [n]);
						tasks [n].Owner = this;
					}

					TaskService.Errors.AddRange (tasks);
					TaskService.Errors.ResetLocationList ();
					IdeApp.Workbench.ActiveLocationList = TaskService.Errors;
					
					tt.Trace ("Reporting result");
					
					string errorString = GettextCatalog.GetPluralString("{0} error", "{0} errors", result.ErrorCount, result.ErrorCount);
					string warningString = GettextCatalog.GetPluralString("{0} warning", "{0} warnings", result.WarningCount, result.WarningCount);

					if (monitor.CancellationToken.IsCancellationRequested) {
						monitor.ReportError (GettextCatalog.GetString ("Build canceled."), null);
					} else if (result.ErrorCount == 0 && result.WarningCount == 0 && lastResult.FailedBuildCount == 0) {
						monitor.ReportSuccess (GettextCatalog.GetString ("Build successful."));
					} else if (result.ErrorCount == 0 && result.WarningCount > 0) {
						monitor.ReportWarning(GettextCatalog.GetString("Build: ") + errorString + ", " + warningString);
					} else if (result.ErrorCount > 0) {
						monitor.ReportError(GettextCatalog.GetString("Build: ") + errorString + ", " + warningString, null);
					} else {
						monitor.ReportError(GettextCatalog.GetString("Build failed."), null);
					}
					tt.Trace ("End build event");
					OnEndBuild (monitor, lastResult.FailedBuildCount == 0, lastResult, entry as SolutionFolderItem);
				} else {
					tt.Trace ("End build event");
					OnEndBuild (monitor, false);
				}
				
				tt.Trace ("Showing results pad");
				
				try {
					Pad errorsPad = IdeApp.Workbench.GetPad<MonoDevelop.Ide.Gui.Pads.ErrorListPad> ();
					switch (IdeApp.Preferences.ShowErrorPadAfterBuild.Value) {
					case BuildResultStates.Always:
						if (!errorsPad.Visible)
							errorsPad.IsOpenedAutomatically = true;
						errorsPad.Visible = true;
						errorsPad.BringToFront ();
						break;
					case BuildResultStates.Never:
						break;
					case BuildResultStates.OnErrors:
						if (TaskService.Errors.Any (task => task.Severity == TaskSeverity.Error))
							goto case BuildResultStates.Always;
						goto case BuildResultStates.Never;
					case BuildResultStates.OnErrorsOrWarnings:
						if (TaskService.Errors.Any (task => task.Severity == TaskSeverity.Error || task.Severity == TaskSeverity.Warning))
							goto case BuildResultStates.Always;
						goto case BuildResultStates.Never;
					}
				} catch {}
				
				if (tasks != null) {
					TaskListEntry jumpTask = null;
					switch (IdeApp.Preferences.JumpToFirstErrorOrWarning.Value) {
					case JumpToFirst.Error:
						jumpTask = tasks.FirstOrDefault (t => t.Severity == TaskSeverity.Error && TaskStore.IsProjectTaskFile (t));
						break;
					case JumpToFirst.ErrorOrWarning:
						jumpTask = tasks.FirstOrDefault (t => (t.Severity == TaskSeverity.Error || t.Severity == TaskSeverity.Warning) && TaskStore.IsProjectTaskFile (t));
						break;
					}
					if (jumpTask != null) {
						tt.Trace ("Jumping to first result position");
						jumpTask.JumpToPosition ();
					}
				}
				
			} finally {
				monitor.Dispose ();
				tt.End ();
			}
		}
		void BuildDone (ProgressMonitor monitor, BuildResult result, IBuildTarget entry, ITimeTracker tt)
		{
			TaskListEntry[] tasks = null;
			tt.Trace ("Begin reporting build result");
			try {
				if (result != null) {
					lastResult = result;
					monitor.Log.WriteLine ();
					monitor.Log.WriteLine (GettextCatalog.GetString ("---------------------- Done ----------------------"));
					
					tt.Trace ("Updating task service");

					tasks = ReportErrors (result);

					tt.Trace ("Reporting result");
					
					string errorString = GettextCatalog.GetPluralString("{0} error", "{0} errors", result.ErrorCount, result.ErrorCount);
					string warningString = GettextCatalog.GetPluralString("{0} warning", "{0} warnings", result.WarningCount, result.WarningCount);

					if (monitor.CancellationToken.IsCancellationRequested) {
						monitor.ReportError (GettextCatalog.GetString ("Build canceled."), null);
					} else if (result.ErrorCount == 0 && result.WarningCount == 0 && lastResult.FailedBuildCount == 0) {
						monitor.ReportSuccess (GettextCatalog.GetString ("Build successful."));
					} else if (result.ErrorCount == 0 && result.WarningCount > 0) {
						monitor.ReportWarning(GettextCatalog.GetString("Build: ") + errorString + ", " + warningString);
					} else if (result.ErrorCount > 0) {
						monitor.ReportError(GettextCatalog.GetString("Build: ") + errorString + ", " + warningString, null);
					} else {
						monitor.ReportError(GettextCatalog.GetString("Build failed."), null);
					}
					tt.Trace ("End build event");
					OnEndBuild (monitor, lastResult.FailedBuildCount == 0, lastResult, entry as SolutionFolderItem);
				} else {
					tt.Trace ("End build event");
					OnEndBuild (monitor, false);
				}
				
				tt.Trace ("Showing results pad");
				
				ShowErrorsPadIfNecessary ();

				if (tasks != null) {
					TaskListEntry jumpTask = null;
					switch (IdeApp.Preferences.JumpToFirstErrorOrWarning.Value) {
					case JumpToFirst.Error:
						jumpTask = tasks.FirstOrDefault (t => t.Severity == TaskSeverity.Error && TaskStore.IsProjectTaskFile (t));
						break;
					case JumpToFirst.ErrorOrWarning:
						jumpTask = tasks.FirstOrDefault (t => (t.Severity == TaskSeverity.Error || t.Severity == TaskSeverity.Warning) && TaskStore.IsProjectTaskFile (t));
						break;
					}
					if (jumpTask != null) {
						tt.Trace ("Jumping to first result position");
						jumpTask.JumpToPosition ();
					}
				}
				
			} finally {
				monitor.Dispose ();
				tt.End ();
			}
		}
		internal static SolutionItem CreateUnknownSolutionItem (ProgressMonitor monitor, string fileName, string typeGuid, string unknownTypeGuid, SolutionLoadContext ctx)
		{
			bool loadAsProject = false;
			string unsupportedMessage;

			var relPath = ctx != null && ctx.Solution != null ? new FilePath (fileName).ToRelative (ctx.Solution.BaseDirectory).ToString() : new FilePath (fileName).FileName;
			var guids = !string.IsNullOrEmpty (unknownTypeGuid) ? unknownTypeGuid.Split (new char[] {';'}, StringSplitOptions.RemoveEmptyEntries) : new string[0];

			if (!string.IsNullOrEmpty (unknownTypeGuid)) {
				var projectInfo = MSBuildProjectService.GetUnknownProjectTypeInfo (guids, fileName);
				if (projectInfo != null) {
					loadAsProject = projectInfo.LoadFiles;
					unsupportedMessage = projectInfo.GetInstructions ();
					LoggingService.LogWarning (string.Format ("Could not load {0} project '{1}'. {2}", projectInfo.Name, relPath, projectInfo.GetInstructions ()));
					monitor.ReportWarning (GettextCatalog.GetString ("Could not load {0} project '{1}'. {2}", projectInfo.Name, relPath, projectInfo.GetInstructions ()));
				} else {
					unsupportedMessage = GettextCatalog.GetString ("Unknown project type: {0}", unknownTypeGuid);
					LoggingService.LogWarning (string.Format ("Could not load project '{0}' with unknown item type '{1}'", relPath, unknownTypeGuid));
					monitor.ReportWarning (GettextCatalog.GetString ("Could not load project '{0}' with unknown item type '{1}'", relPath, unknownTypeGuid));
					return null;
				}
			} else {
				unsupportedMessage = GettextCatalog.GetString ("Unknown project type");
				LoggingService.LogWarning (string.Format ("Could not load project '{0}' with unknown item type", relPath));
				monitor.ReportWarning (GettextCatalog.GetString ("Could not load project '{0}' with unknown item type", relPath));
			}
			if (loadAsProject) {
				var project = (Project) CreateUninitializedInstance (typeof(UnknownProject));
				project.UnsupportedProjectMessage = unsupportedMessage;
				project.SetCreationContext (Project.CreationContext.Create (typeGuid, new string[0]));
				return project;
			} else
				return null;
		}
		public static BuildResult Compile (ProjectItemCollection projectItems, DotNetProjectConfiguration configuration, ConfigurationSelector configSelector, ProgressMonitor monitor)
		{
			var compilerParameters = (CSharpCompilerParameters)configuration.CompilationParameters ?? new CSharpCompilerParameters ();
			var projectParameters = (CSharpProject) configuration.ParentItem;
			
			FilePath outputName = configuration.CompiledOutputName;
			string responseFileName = Path.GetTempFileName ();

			//make sure that the output file is writable
			if (File.Exists (outputName)) {
				bool isWriteable = false;
				int count = 0;
				do {
					try {
						outputName.MakeWritable ();
						using (var stream = File.OpenWrite (outputName)) {
							isWriteable = true;
						}
					} catch (Exception) {
						Thread.Sleep (20);
					}
				} while (count++ < 5 && !isWriteable);
				if (!isWriteable) {
					MessageService.ShowError (string.Format (GettextCatalog.GetString ("Can't lock file: {0}."), outputName));
					return null;
				}
			}

			//get the runtime
			TargetRuntime runtime = MonoDevelop.Core.Runtime.SystemAssemblyService.DefaultRuntime;
			DotNetProject project = configuration.ParentItem as DotNetProject;
			if (project != null)
				runtime = project.TargetRuntime;

			//get the compiler name
			string compilerName;
			try {
				compilerName = GetCompilerName (runtime, configuration.TargetFramework);
			} catch (Exception e) {
				string message = "Could not obtain a C# compiler";
				monitor.ReportError (message, e);
				return null;
			}

			var sb = new StringBuilder ();

			HashSet<string> alreadyAddedReference = new HashSet<string> ();

			var monoRuntime = runtime as MonoTargetRuntime;
			if (!compilerParameters.NoStdLib && (monoRuntime == null || monoRuntime.HasMultitargetingMcs)) {
				string corlib = project.AssemblyContext.GetAssemblyFullName ("mscorlib", project.TargetFramework);
				if (corlib != null) {
					corlib = project.AssemblyContext.GetAssemblyLocation (corlib, project.TargetFramework);
				}
				if (corlib == null) {
					var br = new BuildResult ();
					br.AddError (string.Format ("Could not find mscorlib for framework {0}", project.TargetFramework.Id));
					return br;
				}
				AppendQuoted (sb, "/r:", corlib);
				sb.AppendLine ("-nostdlib");
			}

			List<string> gacRoots = new List<string> ();
			sb.AppendFormat ("\"/out:{0}\"", outputName);
			sb.AppendLine ();
			
			foreach (ProjectReference lib in projectItems.GetAll <ProjectReference> ()) {
				if (lib.ReferenceType == ReferenceType.Project) {
					var ownerProject = lib.OwnerProject;
					if (ownerProject != null) {
						var parentSolution = ownerProject.ParentSolution;
						if (parentSolution != null && !(lib.ResolveProject (parentSolution) is DotNetProject))
							continue;
					}
				} 
				string refPrefix = string.IsNullOrEmpty (lib.Aliases) ? "" : lib.Aliases + "=";
				foreach (string fileName in lib.GetReferencedFileNames (configSelector)) {
					switch (lib.ReferenceType) {
					case ReferenceType.Package:
						SystemPackage pkg = lib.Package;
						if (pkg == null) {
							string msg = string.Format (GettextCatalog.GetString ("{0} could not be found or is invalid."), lib.Reference);
							monitor.ReportWarning (msg);
							continue;
						}

						if (alreadyAddedReference.Add (fileName))
							AppendQuoted (sb, "/r:", refPrefix + fileName);
						
						if (pkg.GacRoot != null && !gacRoots.Contains (pkg.GacRoot))
							gacRoots.Add (pkg.GacRoot);
						if (!string.IsNullOrEmpty (pkg.Requires)) {
							foreach (string requiredPackage in pkg.Requires.Split(' ')) {
								SystemPackage rpkg = runtime.AssemblyContext.GetPackage (requiredPackage);
								if (rpkg == null)
									continue;
								foreach (SystemAssembly assembly in rpkg.Assemblies) {
									if (alreadyAddedReference.Add (assembly.Location))
										AppendQuoted (sb, "/r:", assembly.Location);
								}
							}
						}
						break;
					default:
						if (alreadyAddedReference.Add (fileName))
							AppendQuoted (sb, "/r:", refPrefix + fileName);
						break;
					}
				}
			}

			if (alreadyAddedReference.Any (reference => SystemAssemblyService.ContainsReferenceToSystemRuntime (reference))) {
				LoggingService.LogInfo ("Found PCLv2 assembly.");
				var facades = runtime.FindFacadeAssembliesForPCL (project.TargetFramework);
				foreach (var facade in facades)
					AppendQuoted (sb, "/r:", facade);
			}

			string sysCore = project.AssemblyContext.GetAssemblyFullName ("System.Core", project.TargetFramework);
			if (sysCore != null && !alreadyAddedReference.Contains (sysCore)) {
				var asm = project.AssemblyContext.GetAssemblyFromFullName (sysCore, null, project.TargetFramework);
				if (asm != null)
					AppendQuoted (sb, "/r:", asm.Location);
			}
			
			sb.AppendLine ("/nologo");
			sb.Append ("/warn:");sb.Append (compilerParameters.WarningLevel.ToString ());
			sb.AppendLine ();
			
			if (configuration.SignAssembly) {
				if (File.Exists (configuration.AssemblyKeyFile))
					AppendQuoted (sb, "/keyfile:", configuration.AssemblyKeyFile);
				if (configuration.DelaySign)
					sb.AppendLine ("/delaySign");
			}

			var debugType = configuration.DebugType;
			if (string.IsNullOrEmpty (debugType)) {
				debugType = configuration.DebugSymbols ? "full" : "none";
			} else if (string.Equals (debugType, "pdbonly", StringComparison.OrdinalIgnoreCase)) {
				//old Mono compilers don't support pdbonly
				if (monoRuntime != null && !monoRuntime.HasMultitargetingMcs)
					debugType = "full";
			}
			if (!string.Equals (debugType, "none", StringComparison.OrdinalIgnoreCase)) {
					sb.AppendLine ("/debug:" + debugType);
			}

			if (compilerParameters.LangVersion != LangVersion.Default) {
				var langVersionString = CSharpCompilerParameters.TryLangVersionToString (compilerParameters.LangVersion);
				if (langVersionString == null) {
					string message = "Invalid LangVersion enum value '" + compilerParameters.LangVersion.ToString () + "'";
					monitor.ReportError (message, null);
					LoggingService.LogError (message);
					return null;
				}
				sb.AppendLine ("/langversion:" + langVersionString);
			}
			
			// mcs default is + but others might not be
			if (compilerParameters.Optimize)
				sb.AppendLine ("/optimize+");
			else
				sb.AppendLine ("/optimize-");
			
			bool hasWin32Res = !string.IsNullOrEmpty (projectParameters.Win32Resource) && File.Exists (projectParameters.Win32Resource);
			if (hasWin32Res) 
				AppendQuoted (sb, "/win32res:", projectParameters.Win32Resource);
			
			if (!string.IsNullOrEmpty (projectParameters.Win32Icon) && File.Exists (projectParameters.Win32Icon)) {
				if (hasWin32Res) {
					monitor.ReportWarning ("Both Win32 icon and Win32 resource cannot be specified. Ignoring the icon.");
				} else {
					AppendQuoted (sb, "/win32icon:", projectParameters.Win32Icon);
				}
			}
			
			if (projectParameters.CodePage != 0)
				sb.AppendLine ("/codepage:" + projectParameters.CodePage);
			else if (runtime is MonoTargetRuntime)
				sb.AppendLine ("/codepage:utf8");
			
			if (compilerParameters.UnsafeCode) 
				sb.AppendLine ("-unsafe");
			if (compilerParameters.NoStdLib) 
				sb.AppendLine ("-nostdlib");
			
			if (!string.IsNullOrEmpty (compilerParameters.PlatformTarget) && compilerParameters.PlatformTarget.ToLower () != "anycpu") {
				//HACK: to ignore the platform flag for Mono <= 2.4, because gmcs didn't support it
				if (runtime.RuntimeId == "Mono" && runtime.AssemblyContext.GetAssemblyLocation ("Mono.Debugger.Soft", null) == null) {
					LoggingService.LogWarning ("Mono runtime '" + runtime.DisplayName + 
					                           "' appears to be too old to support the 'platform' C# compiler flag.");
				} else {
					sb.AppendLine ("/platform:" + compilerParameters.PlatformTarget);
				}
			}

			if (compilerParameters.TreatWarningsAsErrors) {
				sb.AppendLine ("-warnaserror");
				if (!string.IsNullOrEmpty (compilerParameters.WarningsNotAsErrors))
					sb.AppendLine ("-warnaserror-:" + compilerParameters.WarningsNotAsErrors);
			}

			foreach (var define in configuration.GetDefineSymbols ()) {
				AppendQuoted (sb, "/define:", define);
				sb.AppendLine ();
			}

			CompileTarget ctarget = configuration.CompileTarget;
			
			if (!string.IsNullOrEmpty (projectParameters.MainClass)) {
				sb.AppendLine ("/main:" + projectParameters.MainClass);
				// mcs does not allow providing a Main class when compiling a dll
				// As a workaround, we compile as WinExe (although the output will still
				// have a .dll extension).
				if (ctarget == CompileTarget.Library)
					ctarget = CompileTarget.WinExe;
			}
			
			switch (ctarget) {
				case CompileTarget.Exe:
					sb.AppendLine ("/t:exe");
					break;
				case CompileTarget.WinExe:
					sb.AppendLine ("/t:winexe");
					break;
				case CompileTarget.Library:
					sb.AppendLine ("/t:library");
					break;
			}
			
			foreach (ProjectFile finfo in projectItems.GetAll<ProjectFile> ()) {
				if (finfo.Subtype == Subtype.Directory)
					continue;

				switch (finfo.BuildAction) {
					case "Compile":
						AppendQuoted (sb, "", finfo.Name);
						break;
					case "EmbeddedResource":
						string fname = finfo.Name;
						if (string.Compare (Path.GetExtension (fname), ".resx", StringComparison.OrdinalIgnoreCase) == 0)
							fname = Path.ChangeExtension (fname, ".resources");
						sb.Append ('"');sb.Append ("/res:");
						sb.Append (fname);sb.Append (',');sb.Append (finfo.ResourceId);
						sb.Append ('"');sb.AppendLine ();
						break;
					default:
						continue;
				}
			}
			if (!compilerParameters.DocumentationFile.IsNullOrEmpty) 
				AppendQuoted (sb, "/doc:", compilerParameters.DocumentationFile);
			
			if (!string.IsNullOrEmpty (compilerParameters.NoWarnings)) 
				AppendQuoted (sb, "/nowarn:", compilerParameters.NoWarnings);

			if (runtime.RuntimeId == "MS.NET") {
				sb.AppendLine("/fullpaths");
				sb.AppendLine("/utf8output");
			}

			string output = "";
			string error  = "";
			
			File.WriteAllText (responseFileName, sb.ToString ());

			monitor.Log.WriteLine (compilerName + " /noconfig " + sb.ToString ().Replace ('\n',' '));

			// Dummy projects created for single files have no filename
			// and so no BaseDirectory.
			string workingDir = null;
			if (configuration.ParentItem != null)
				workingDir = configuration.ParentItem.BaseDirectory;

			LoggingService.LogInfo (compilerName + " " + sb);

			ExecutionEnvironment envVars = runtime.GetToolsExecutionEnvironment (project.TargetFramework);
			string cargs = "/noconfig @\"" + responseFileName + "\"";

			int exitCode = DoCompilation (monitor, compilerName, cargs, workingDir, envVars, gacRoots, ref output, ref error);
			
			BuildResult result = ParseOutput (workingDir, output, error);
			if (result.CompilerOutput.Trim ().Length != 0)
				monitor.Log.WriteLine (result.CompilerOutput);
			
			//if compiler crashes, output entire error string
			if (result.ErrorCount == 0 && exitCode != 0) {
				try {
					monitor.Log.Write (File.ReadAllText (error));
				} catch (IOException) {
				}
				result.AddError ("The compiler appears to have crashed. Check the build output pad for details.");
				LoggingService.LogError ("C# compiler crashed. Response file '{0}', stdout file '{1}', stderr file '{2}'",
				                         responseFileName, output, error);
			} else {
				FileService.DeleteFile (responseFileName);
				FileService.DeleteFile (output);
				FileService.DeleteFile (error);
			}
			return result;
		}