Esempio n. 1
0
		public BuildEngine4 (BuildSubmission submission)
		{
			this.submission = submission;
			event_source = new Microsoft.Build.BuildEngine.EventSource ();
			if (submission.BuildManager.OngoingBuildParameters.Loggers != null)
				foreach (var l in submission.BuildManager.OngoingBuildParameters.Loggers)
					l.Initialize (event_source);
		}
Esempio n. 2
0
        public BuildSubmission PendBuildRequest(BuildRequestData requestData)
        {
            if (ongoing_build_parameters == null)
            {
                throw new InvalidOperationException("This method cannot be called before calling BeginBuild method.");
            }
            var sub = new BuildSubmission(this, requestData);

            submissions.Add(sub);
            return(sub);
        }
        public void BuildAndAnalyze()
        {
            var globalProps = new Dictionary<string, string> {
                {"VisualStudioVersion","12.0"}
            };
            pc = new ProjectCollection(globalProps);

            var diagLogger = new DiagnosticXmlLogger(this);
            diagLogger.LogFile = _logFilepath;

            project = pc.LoadProject(_projectFilepath, "12.0");
            projInst = project.CreateProjectInstance();
            buildManager = new BuildManager();
            var buildParams = new BuildParameters();
            buildParams.Loggers = new ILogger[] { diagLogger };
            buildManager.BeginBuild(buildParams);

            var brd = new BuildRequestData(projInst, _targets, null, BuildRequestDataFlags.ReplaceExistingProjectInstance);
            submission = buildManager.PendBuildRequest(brd);
            buildResult = submission.Execute();

            buildManager.EndBuild();
        }
Esempio n. 4
0
        /// <summary>
        /// Lets Visual Studio know that we're done with our design-time build so others can use the build manager.
        /// </summary>
        /// <param name="submission">The build submission that built, if any.</param>
        /// <param name="designTime">This must be the same value as the one passed to <see cref="TryBeginBuild"/>.</param>
        /// <param name="requiresUIThread">This must be the same value as the one passed to <see cref="TryBeginBuild"/>.</param>
        /// <remarks>
        /// This method must be called on the UI thread.
        /// </remarks>
        private void EndBuild(BuildSubmission submission, bool designTime, bool requiresUIThread = false)
        {
            IVsBuildManagerAccessor accessor = null;

            if (this.Site != null)
            {
                accessor = this.Site.GetService(typeof(SVsBuildManagerAccessor)) as IVsBuildManagerAccessor;
            }

            if (accessor != null)
            {
                // It's very important that we try executing all three end-build steps, even if errors occur partway through.
                try
                {
                    if (submission != null)
                    {
                        Marshal.ThrowExceptionForHR(accessor.UnregisterLoggers(submission.SubmissionId));
                    }
                }
                catch (Exception ex)
                {
                    if (ErrorHandler.IsCriticalException(ex))
                    {
                        throw;
                    }

                    Trace.TraceError(ex.ToString());
                }

                try
                {
                    if (designTime)
                    {
                        Marshal.ThrowExceptionForHR(accessor.EndDesignTimeBuild());
                    }
                }
                catch (Exception ex)
                {
                    if (ErrorHandler.IsCriticalException(ex))
                    {
                        throw;
                    }

                    Trace.TraceError(ex.ToString());
                }

                try
                {
                    if (requiresUIThread)
                    {
                        Marshal.ThrowExceptionForHR(accessor.ReleaseUIThreadForBuild());
                    }
                }
                catch (Exception ex)
                {
                    if (ErrorHandler.IsCriticalException(ex))
                    {
                        throw;
                    }

                    Trace.TraceError(ex.ToString());
                }
            }
            else
            {
                BuildManager.DefaultBuildManager.EndBuild();
            }

            this.buildInProcess = false;
        }
Esempio n. 5
0
        internal static bool BuildProject
        (
            string projectFile,
            string[] targets,
            string toolsVersion,
            Dictionary<string, string> globalProperties,
            ILogger[] loggers,
            LoggerVerbosity verbosity,
            DistributedLoggerRecord[] distributedLoggerRecords,
            bool needToValidateProject,
            string schemaFile,
            int cpuCount,
            bool enableNodeReuse,
            TextWriter preprocessWriter,
            bool debugger,
            bool detailedSummary
        )
        {
            if (String.Equals(Path.GetExtension(projectFile), ".vcproj", StringComparison.OrdinalIgnoreCase) ||
                String.Equals(Path.GetExtension(projectFile), ".dsp", StringComparison.OrdinalIgnoreCase))
            {
                InitializationException.Throw(ResourceUtilities.FormatResourceString("ProjectUpgradeNeededToVcxProj", projectFile), null);
            }

            bool success = false;

            ProjectCollection projectCollection = null;
            bool onlyLogCriticalEvents = false;

            try
            {
                List<ForwardingLoggerRecord> remoteLoggerRecords = new List<ForwardingLoggerRecord>();
                foreach (DistributedLoggerRecord distRecord in distributedLoggerRecords)
                {
                    remoteLoggerRecords.Add(new ForwardingLoggerRecord(distRecord.CentralLogger, distRecord.ForwardingLoggerDescription));
                }

                // Targeted perf optimization for the case where we only have our own parallel console logger, and verbosity is quiet. In such a case
                // we know we won't emit any messages except for errors and warnings, so the engine should not bother even logging them.
                // If we're using the original serial console logger we can't do this, as it shows project started/finished context
                // around errors and warnings.
                // Telling the engine to not bother logging non-critical messages means that typically it can avoid loading any resources in the successful
                // build case.
                if (loggers.Length == 1 &&
                    remoteLoggerRecords.Count == 0 &&
                    verbosity == LoggerVerbosity.Quiet &&
                    loggers[0].Parameters != null &&
                    loggers[0].Parameters.IndexOf("ENABLEMPLOGGING", StringComparison.OrdinalIgnoreCase) != -1 &&
                    loggers[0].Parameters.IndexOf("DISABLEMPLOGGING", StringComparison.OrdinalIgnoreCase) == -1 &&
                    loggers[0].Parameters.IndexOf("V=", StringComparison.OrdinalIgnoreCase) == -1 &&                // Console logger could have had a verbosity
                    loggers[0].Parameters.IndexOf("VERBOSITY=", StringComparison.OrdinalIgnoreCase) == -1)          // override with the /clp switch
                {
                    // Must be exactly the console logger, not a derived type like the file logger.
                    Type t1 = loggers[0].GetType();
                    Type t2 = typeof(ConsoleLogger);
                    if (t1 == t2)
                    {
                        onlyLogCriticalEvents = true;
                    }
                }

                // HACK HACK: this enables task parameter logging.
                // This is a hack for now to make sure the perf hit only happens
                // on diagnostic. This should be changed to pipe it through properly,
                // perhaps as part of a fuller tracing feature.
                bool logTaskInputs = verbosity == LoggerVerbosity.Diagnostic;

                if (!logTaskInputs)
                {
                    foreach (var logger in loggers)
                    {
                        if (logger.Parameters != null &&
                            (logger.Parameters.IndexOf("V=DIAG", StringComparison.OrdinalIgnoreCase) != -1 ||
                             logger.Parameters.IndexOf("VERBOSITY=DIAG", StringComparison.OrdinalIgnoreCase) != -1)
                           )
                        {
                            logTaskInputs = true;
                            break;
                        }
                    }
                }

                if (!logTaskInputs)
                {
                    foreach (var logger in distributedLoggerRecords)
                    {
                        if (logger.CentralLogger != null)
                        {
                            if (logger.CentralLogger.Parameters != null &&
                                (logger.CentralLogger.Parameters.IndexOf("V=DIAG", StringComparison.OrdinalIgnoreCase) != -1 ||
                                 logger.CentralLogger.Parameters.IndexOf("VERBOSITY=DIAG", StringComparison.OrdinalIgnoreCase) != -1)
                               )
                            {
                                logTaskInputs = true;
                                break;
                            }
                        }
                    }
                }

                projectCollection = new ProjectCollection
                        (
                        globalProperties,
                        loggers,
                        null,
                        Microsoft.Build.Evaluation.ToolsetDefinitionLocations.ConfigurationFile | Microsoft.Build.Evaluation.ToolsetDefinitionLocations.Registry,
                        cpuCount,
                        onlyLogCriticalEvents
                        );

                if (debugger)
                {
                    // Debugging is not currently fully supported so we don't want to open
                    // public API for it. Also, we want to have a way to make it work when running inside VS.
                    // So use an environment variable. The undocumented /debug switch is just an easy way to set it.
                    Environment.SetEnvironmentVariable("MSBUILDDEBUGGING", "1");
                }

                if (toolsVersion != null && !projectCollection.ContainsToolset(toolsVersion))
                {
                    ThrowInvalidToolsVersionInitializationException(projectCollection.Toolsets, toolsVersion);
                }

                // If the user has requested that the schema be validated, do that here. 
                if (needToValidateProject && !FileUtilities.IsSolutionFilename(projectFile))
                {
                    Microsoft.Build.Evaluation.Project project = projectCollection.LoadProject(projectFile, globalProperties, toolsVersion);
                    Microsoft.Build.Evaluation.Toolset toolset = projectCollection.GetToolset((toolsVersion == null) ? project.ToolsVersion : toolsVersion);

                    if (toolset == null)
                    {
                        ThrowInvalidToolsVersionInitializationException(projectCollection.Toolsets, project.ToolsVersion);
                    }

                    ProjectSchemaValidationHandler.VerifyProjectSchema(projectFile, schemaFile, toolset.ToolsPath);

                    // If there are schema validation errors, an InitializationException is thrown, so if we get here,
                    // we can safely assume that the project successfully validated. 
                    projectCollection.UnloadProject(project);
                }

                if (preprocessWriter != null && !FileUtilities.IsSolutionFilename(projectFile))
                {
                    Project project = projectCollection.LoadProject(projectFile, globalProperties, toolsVersion);

                    project.SaveLogicalProject(preprocessWriter);

                    projectCollection.UnloadProject(project);
                    success = true;
                }
                else
                {
                    BuildRequestData request = new BuildRequestData(projectFile, globalProperties, toolsVersion, targets, null);

                    BuildParameters parameters = new BuildParameters(projectCollection);

                    // By default we log synchronously to the console for compatibility with previous versions,
                    // but it is slightly slower
                    if (!String.Equals(Environment.GetEnvironmentVariable("MSBUILDLOGASYNC"), "1", StringComparison.Ordinal))
                    {
                        parameters.UseSynchronousLogging = true;
                    }

                    parameters.EnableNodeReuse = enableNodeReuse;
                    parameters.NodeExeLocation = Assembly.GetExecutingAssembly().Location;
                    parameters.MaxNodeCount = cpuCount;
                    parameters.Loggers = projectCollection.Loggers;
                    parameters.ForwardingLoggers = remoteLoggerRecords;
                    parameters.ToolsetDefinitionLocations = Microsoft.Build.Evaluation.ToolsetDefinitionLocations.ConfigurationFile | Microsoft.Build.Evaluation.ToolsetDefinitionLocations.Registry;
                    parameters.DetailedSummary = detailedSummary;
                    parameters.LogTaskInputs = logTaskInputs;

                    if (!String.IsNullOrEmpty(toolsVersion))
                    {
                        parameters.DefaultToolsVersion = toolsVersion;
                    }

                    string memoryUseLimit = Environment.GetEnvironmentVariable("MSBUILDMEMORYUSELIMIT");
                    if (!String.IsNullOrEmpty(memoryUseLimit))
                    {
                        parameters.MemoryUseLimit = Convert.ToInt32(memoryUseLimit, CultureInfo.InvariantCulture);

                        // The following ensures that when we divide the use by node count to get the per-limit amount, we always end up with a 
                        // positive value - otherwise setting it too low will result in a zero, which will enable only the default cache behavior
                        // which is not what is intended by using this environment variable.
                        if (parameters.MemoryUseLimit < parameters.MaxNodeCount)
                        {
                            parameters.MemoryUseLimit = parameters.MaxNodeCount;
                        }
                    }

                    BuildManager buildManager = BuildManager.DefaultBuildManager;

#if MSBUILDENABLEVSPROFILING 
                    DataCollection.CommentMarkProfile(8800, "Pending Build Request from MSBuild.exe");
#endif
                    BuildResult results = null;
                    buildManager.BeginBuild(parameters);
                    Exception exception = null;
                    try
                    {
                        try
                        {
                            lock (s_buildLock)
                            {
                                s_activeBuild = buildManager.PendBuildRequest(request);

                                // Even if Ctrl-C was already hit, we still pend the build request and then cancel.
                                // That's so the build does not appear to have completed successfully.
                                if (s_receivedCancel == 1)
                                {
                                    buildManager.CancelAllSubmissions();
                                }
                            }

                            results = s_activeBuild.Execute();
                        }
                        finally
                        {
                            buildManager.EndBuild();
                        }
                    }
                    catch (Exception ex)
                    {
                        exception = ex;
                        success = false;
                    }

                    if (results != null && exception == null)
                    {
                        success = results.OverallResult == BuildResultCode.Success;
                        exception = results.Exception;
                    }

                    if (exception != null)
                    {
                        success = false;

                        // InvalidProjectFileExceptions have already been logged.
                        if (exception.GetType() != typeof(InvalidProjectFileException))
                        {
                            if
                                (
                                exception.GetType() == typeof(LoggerException) ||
                                exception.GetType() == typeof(InternalLoggerException)
                                )
                            {
                                // We will rethrow this so the outer exception handler can catch it, but we don't
                                // want to log the outer exception stack here.
                                throw exception;
                            }

                            if (exception.GetType() == typeof(BuildAbortedException))
                            {
                                // this is not a bug and should not dump stack. It will already have been logged
                                // appropriately, there is no need to take any further action with it.
                            }
                            else
                            {
                                // After throwing again below the stack will be reset. Make certain we log everything we 
                                // can now
                                Console.WriteLine(AssemblyResources.GetString("FatalError"));
#if DEBUG
                                Console.WriteLine("This is an unhandled exception in MSBuild -- PLEASE OPEN A BUG AGAINST THE MSBUILD TEAM.");
#endif
                                Console.WriteLine(exception.ToString());
                                Console.WriteLine();

                                throw exception;
                            }
                        }
                    }
                }
            }
            // handle project file errors
            catch (InvalidProjectFileException ex)
            {
                // just eat the exception because it has already been logged
                ErrorUtilities.VerifyThrow(ex.HasBeenLogged, "Should have been logged");
                success = false;
            }
            finally
            {
                FileUtilities.ClearCacheDirectory();
                if (projectCollection != null)
                {
                    projectCollection.Dispose();
                }

                BuildManager.DefaultBuildManager.Dispose();
            }

            return success;
        }
 private static void SetBuildComplete(BuildSubmission submission)
 {
     var tcs = (TaskCompletionSource<BuildResult>)submission.AsyncContext;
     tcs.SetResult(submission.BuildResult);
 }
Esempio n. 7
0
 public BuildResult(BuildSubmission submission, ProjectInstance projectInstance) :
         this(submission.BuildResult.OverallResult == BuildResultCode.Success ? MSBuildResult.Successful : MSBuildResult.Failed, projectInstance)
 {
 }
Esempio n. 8
0
		public BuildSubmission PendBuildRequest (BuildRequestData requestData)
		{
			if (ongoing_build_parameters == null)
				throw new InvalidOperationException ("This method cannot be called before calling BeginBuild method.");
			var sub = new BuildSubmission (this, requestData);
			submissions.Add (sub);
			return sub;
		}
Esempio n. 9
0
		public void Enqueue (BuildSubmission build)
		{
			queued_builds.Enqueue (build);
			queue_wait_handle.Set ();
		}
Esempio n. 10
0
			public void Release ()
			{
				Build = null;
				IsAvailable = true;
			}
Esempio n. 11
0
			public void Assign (BuildSubmission build)
			{
				IsAvailable = false;
				Build = build;
			}
Esempio n. 12
0
		// FIXME: take max nodes into account here, and get throttling working.
		BuildNode TakeNode (BuildSubmission build)
		{
			var host = BuildManager.OngoingBuildParameters.HostServices;
			NodeAffinity affinity;
			if (host == null)
				affinity = NodeAffinity.Any;
			else
				affinity = host.GetNodeAffinity (build.BuildRequest.ProjectFullPath);
			BuildNode n = GetReusableNode (affinity);
			if (n != null)
				n.Assign (build);
			else {
				n = new BuildNode (this, affinity == NodeAffinity.Any ? NodeAffinity.InProc : affinity);
				n.Assign (build);
				if (n.Affinity == NodeAffinity.InProc)
					in_proc_nodes.Add (n);
				else
					out_proc_nodes.Add (n);
			}
			return n;
		}
Esempio n. 13
0
		void StartOneBuild (BuildSubmission build)
		{
			var node = TakeNode (build);
			// FIXME: Task (non-generic) here causes NotImplementedException in somewhere in Interlocked. It does not make sense.
			ongoing_builds [build] = task_factory.StartNew (node.ExecuteBuild);
			//new Thread (() => { node.ExecuteBuild (); }).Start ();
		}