public void RemoveToolset() { ProjectCollection collection = new ProjectCollection(); Toolset toolset1 = new Toolset("x", "c:\\y", collection, null); Toolset toolset2 = new Toolset("y", "c:\\z", collection, null); int initial = Helpers.MakeList<Toolset>(collection.Toolsets).Count; collection.AddToolset(toolset1); collection.AddToolset(toolset2); Assert.Equal(true, collection.RemoveToolset("x")); Assert.Equal(false, collection.ContainsToolset("x")); Assert.Equal(1, Helpers.MakeList<Toolset>(collection.Toolsets).Count - initial); }
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; }
public void AddToolset() { ProjectCollection collection = new ProjectCollection(); collection.RemoveAllToolsets(); Toolset toolset = new Toolset("x", "c:\\y", collection, null); collection.AddToolset(toolset); Assert.Equal(toolset, collection.GetToolset("x")); Assert.Equal(true, collection.ContainsToolset("x")); List<Toolset> toolsets = Helpers.MakeList(collection.Toolsets); Assert.Equal(1, toolsets.Count); Assert.Equal(toolset, toolsets[0]); }