public void ReevaluationShouldNotReuseInitialContext(EvaluationContext.SharingPolicy policy) { try { EvaluationContext.TestOnlyHookOnCreate = c => SetResolverForContext(c, _resolver); var collection = _env.CreateProjectCollection().Collection; var context = EvaluationContext.Create(policy); var project = Project.FromXmlReader( XmlReader.Create(new StringReader("<Project Sdk=\"foo\"></Project>")), new ProjectOptions { ProjectCollection = collection, EvaluationContext = context, LoadSettings = ProjectLoadSettings.IgnoreMissingImports }); _resolver.ResolvedCalls["foo"].ShouldBe(1); project.AddItem("a", "b"); project.ReevaluateIfNecessary(); _resolver.ResolvedCalls["foo"].ShouldBe(2); } finally { EvaluationContext.TestOnlyHookOnCreate = null; } }
public void PassedInFileSystemShouldBeReusedInSharedContext() { var projectFiles = new[] { _env.CreateFile("1.proj", @"<Project> <PropertyGroup Condition=`Exists('1.file')`></PropertyGroup> </Project>".Cleanup()).Path, _env.CreateFile("2.proj", @"<Project> <PropertyGroup Condition=`Exists('2.file')`></PropertyGroup> </Project>".Cleanup()).Path }; var projectCollection = _env.CreateProjectCollection().Collection; var fileSystem = new Helpers.LoggingFileSystem(); var evaluationContext = EvaluationContext.Create(EvaluationContext.SharingPolicy.Shared, fileSystem); foreach (var projectFile in projectFiles) { Project.FromFile( projectFile, new ProjectOptions { ProjectCollection = projectCollection, EvaluationContext = evaluationContext } ); } fileSystem.ExistenceChecks.OrderBy(kvp => kvp.Key) .ShouldBe( new Dictionary <string, int> { { Path.Combine(_env.DefaultTestDirectory.Path, "1.file"), 1 }, { Path.Combine(_env.DefaultTestDirectory.Path, "2.file"), 1 } }.OrderBy(kvp => kvp.Key)); fileSystem.FileOrDirectoryExistsCalls.ShouldBe(2); }
public void SharedContextShouldGetReusedWhereasIsolatedContextShouldNot(EvaluationContext.SharingPolicy policy) { var previousContext = EvaluationContext.Create(policy); for (var i = 0; i < 10; i++) { var currentContext = previousContext.ContextForNewProject(); if (i == 0) { currentContext.ShouldBeSameAs(previousContext, "first usage context was not the same as the initial context"); } else { switch (policy) { case EvaluationContext.SharingPolicy.Shared: currentContext.ShouldBeSameAs(previousContext, $"Shared policy: usage {i} was not the same as usage {i - 1}"); break; case EvaluationContext.SharingPolicy.Isolated: currentContext.ShouldNotBeSameAs(previousContext, $"Isolated policy: usage {i} was the same as usage {i - 1}"); break; default: throw new ArgumentOutOfRangeException(nameof(policy), policy, null); } } previousContext = currentContext; } }
public void ReevaluationShouldRespectContextLifetime(EvaluationContext.SharingPolicy policy) { var collection = _env.CreateProjectCollection().Collection; var context1 = EvaluationContext.Create(policy); var project = Project.FromXmlReader( XmlReader.Create(new StringReader("<Project></Project>")), new ProjectOptions { ProjectCollection = collection, EvaluationContext = context1, LoadSettings = ProjectLoadSettings.IgnoreMissingImports }); project.AddItem("a", "b"); project.ReevaluateIfNecessary(); var context2 = GetEvaluationContext(project); switch (policy) { case EvaluationContext.SharingPolicy.Shared: context1.ShouldBeSameAs(context2); break; case EvaluationContext.SharingPolicy.Isolated: context1.ShouldNotBeSameAs(context2); break; } }
public void ContextPinsGlobExpansionCache(EvaluationContext.SharingPolicy policy, string[][] expectedGlobExpansions) { var projectDirectory = _env.DefaultTestDirectory.FolderPath; _env.SetCurrentDirectory(projectDirectory); var context = EvaluationContext.Create(policy); var evaluationCount = 0; File.WriteAllText(Path.Combine(projectDirectory, $"{evaluationCount}.cs"), ""); EvaluateProjects( _globProjects, context, project => { var expectedGlobExpansion = expectedGlobExpansions[evaluationCount]; evaluationCount++; File.WriteAllText(Path.Combine(projectDirectory, $"{evaluationCount}.cs"), ""); ObjectModelHelpers.AssertItems(expectedGlobExpansion, project.GetItems("i")); } ); }
public void ContextDisambiguatesAFullyQualifiedGlobPointingInAnotherRelativeGlobsCone(EvaluationContext.SharingPolicy policy, string[][] expectedGlobExpansions) { var project1Directory = _env.DefaultTestDirectory.CreateDirectory("Project1"); var project1GlobDirectory = project1Directory.CreateDirectory("Glob").CreateDirectory("1").Path; var project2Directory = _env.DefaultTestDirectory.CreateDirectory("Project2"); var context = EvaluationContext.Create(policy); var evaluationCount = 0; File.WriteAllText(Path.Combine(project1GlobDirectory, $"{evaluationCount}.cs"), ""); EvaluateProjects( new [] { // first project uses a relative path new ProjectSpecification( Path.Combine(project1Directory.Path, "1"), $@"<Project> <ItemGroup> <i Include=`{Path.Combine("Glob", "**", "*.cs")}` /> </ItemGroup> </Project>"), // second project reaches out into first project's cone via a fully qualified path new ProjectSpecification( Path.Combine(project2Directory.Path, "2"), $@"<Project> <ItemGroup> <i Include=`{Path.Combine(project1Directory.Path, "Glob", "**", "*.cs")}` /> </ItemGroup> </Project>") }, context, project => { var projectName = Path.GetFileNameWithoutExtension(project.FullPath); // globs have the fixed directory part prepended, so add it to the expected results var expectedGlobExpansion = expectedGlobExpansions[evaluationCount] .Select(i => Path.Combine("Glob", "1", i)) .ToArray(); // project 2 has fully qualified directory parts, so make the results for 2 fully qualified if (projectName.Equals("2")) { expectedGlobExpansion = expectedGlobExpansion .Select(i => Path.Combine(project1Directory.Path, i)) .ToArray(); } var actualGlobExpansion = project.GetItems("i"); ObjectModelHelpers.AssertItems(expectedGlobExpansion, actualGlobExpansion); evaluationCount++; File.WriteAllText(Path.Combine(project1GlobDirectory, $"{evaluationCount}.cs"), ""); } ); }
public void ProjectInstanceShouldRespectSharingPolicy(EvaluationContext.SharingPolicy policy) { try { var seenContexts = new HashSet <EvaluationContext>(); EvaluationContext.TestOnlyHookOnCreate = c => seenContexts.Add(c); var collection = _env.CreateProjectCollection().Collection; var context = EvaluationContext.Create(policy); const int numIterations = 10; for (int i = 0; i < numIterations; i++) { ProjectInstance.FromProjectRootElement( ProjectRootElement.Create(), new ProjectOptions { ProjectCollection = collection, EvaluationContext = context, LoadSettings = ProjectLoadSettings.IgnoreMissingImports }); } int expectedNumContexts = policy == EvaluationContext.SharingPolicy.Shared ? 1 : numIterations; seenContexts.Count.ShouldBe(expectedNumContexts); seenContexts.ShouldAllBe(c => c.Policy == policy); } finally { EvaluationContext.TestOnlyHookOnCreate = null; } }
public void IsolatedContextShouldNotSupportBeingPassedAFileSystem() { _env.DoNotLaunchDebugger(); var fileSystem = new Helpers.LoggingFileSystem(); Should.Throw <ArgumentException>(() => EvaluationContext.Create(EvaluationContext.SharingPolicy.Isolated, fileSystem)); }
public void ContextDisambiguatesDistinctRelativeGlobsPointingOutsideOfSameProjectCone(EvaluationContext.SharingPolicy policy, string[][] expectedGlobExpansions) { var globDirectory = _env.DefaultTestDirectory.CreateDirectory("glob"); var projectRoot = _env.DefaultTestDirectory.CreateDirectory("proj"); var project1Directory = projectRoot.CreateDirectory("Project1"); var project2SubDir = projectRoot.CreateDirectory("subdirectory"); var project2Directory = project2SubDir.CreateDirectory("Project2"); var context = EvaluationContext.Create(policy); var evaluationCount = 0; File.WriteAllText(Path.Combine(globDirectory.Path, $"{evaluationCount}.cs"), ""); EvaluateProjects( new [] { new ProjectSpecification( Path.Combine(project1Directory.Path, "1"), @"<Project> <ItemGroup> <i Include=`../../glob/*.cs` /> </ItemGroup> </Project>"), new ProjectSpecification( Path.Combine(project2Directory.Path, "2"), @"<Project> <ItemGroup> <i Include=`../../../glob/*.cs` /> </ItemGroup> </Project>") }, context, project => { var projectName = Path.GetFileNameWithoutExtension(project.FullPath); var globFixedDirectoryPart = projectName.EndsWith("1") ? Path.Combine("..", "..", "glob") : Path.Combine("..", "..", "..", "glob"); // globs have the fixed directory part prepended, so add it to the expected results var expectedGlobExpansion = expectedGlobExpansions[evaluationCount] .Select(i => Path.Combine(globFixedDirectoryPart, i)) .ToArray(); var actualGlobExpansion = project.GetItems("i"); ObjectModelHelpers.AssertItems(expectedGlobExpansion, actualGlobExpansion); evaluationCount++; File.WriteAllText(Path.Combine(globDirectory.Path, $"{evaluationCount}.cs"), ""); } ); }
private void ContextCachesCommonOutOfProjectCone(bool itemSpecPathIsRelative, EvaluationContext.SharingPolicy policy, string[][] expectedGlobExpansions) { var testDirectory = _env.DefaultTestDirectory; var globDirectory = testDirectory.CreateDirectory("GlobDirectory"); var itemSpecDirectoryPart = itemSpecPathIsRelative ? Path.Combine("..", "GlobDirectory") : globDirectory.Path; Directory.CreateDirectory(globDirectory.Path); // Globs with a directory part will produce items prepended with that directory part foreach (var globExpansion in expectedGlobExpansions) { for (var i = 0; i < globExpansion.Length; i++) { globExpansion[i] = Path.Combine(itemSpecDirectoryPart, globExpansion[i]); } } var projectSpecs = new[] { $@"<Project> <ItemGroup> <i Include=`{Path.Combine("{0}", "**", "*.cs")}`/> </ItemGroup> </Project>", $@"<Project> <ItemGroup> <i Include=`{Path.Combine("{0}", "**", "*.cs")}`/> </ItemGroup> </Project>" } .Select(p => string.Format(p, itemSpecDirectoryPart)) .Select((p, i) => new ProjectSpecification(Path.Combine(testDirectory.Path, $"ProjectDirectory{i}", $"Project{i}.proj"), p)); var context = EvaluationContext.Create(policy); var evaluationCount = 0; File.WriteAllText(Path.Combine(globDirectory.Path, $"{evaluationCount}.cs"), ""); EvaluateProjects( projectSpecs, context, project => { var expectedGlobExpansion = expectedGlobExpansions[evaluationCount]; evaluationCount++; File.WriteAllText(Path.Combine(globDirectory.Path, $"{evaluationCount}.cs"), ""); ObjectModelHelpers.AssertItems(expectedGlobExpansion, project.GetItems("i")); } ); }
public void ContextDisambiguatesSameRelativeGlobsPointingOutsideDifferentProjectCones(EvaluationContext.SharingPolicy policy, string[][] expectedGlobExpansions) { var project1Root = _env.DefaultTestDirectory.CreateDirectory("Project1"); var project1Directory = project1Root.CreateDirectory("1").Path; var project1GlobDirectory = project1Root.CreateDirectory("Glob").CreateDirectory("1").Path; var project2Root = _env.DefaultTestDirectory.CreateDirectory("Project2"); var project2Directory = project2Root.CreateDirectory("2").Path; var project2GlobDirectory = project2Root.CreateDirectory("Glob").CreateDirectory("2").Path; var context = EvaluationContext.Create(policy); var evaluationCount = 0; File.WriteAllText(Path.Combine(project1GlobDirectory, $"1.{evaluationCount}.cs"), ""); File.WriteAllText(Path.Combine(project2GlobDirectory, $"2.{evaluationCount}.cs"), ""); EvaluateProjects( new [] { new ProjectSpecification( Path.Combine(project1Directory, "1"), $@"<Project> <ItemGroup> <i Include=`{Path.Combine("..", "Glob", "**", "*.cs")}`/> </ItemGroup> </Project>"), new ProjectSpecification( Path.Combine(project2Directory, "2"), $@"<Project> <ItemGroup> <i Include=`{Path.Combine("..", "Glob", "**", "*.cs")}`/> </ItemGroup> </Project>") }, context, project => { var projectName = Path.GetFileNameWithoutExtension(project.FullPath); // globs have the fixed directory part prepended, so add it to the expected results var expectedGlobExpansion = expectedGlobExpansions[evaluationCount] .Select(i => Path.Combine("..", "Glob", projectName, $"{projectName}.{i}")) .ToArray(); var actualGlobExpansion = project.GetItems("i"); ObjectModelHelpers.AssertItems(expectedGlobExpansion, actualGlobExpansion); evaluationCount++; File.WriteAllText(Path.Combine(project1GlobDirectory, $"1.{evaluationCount}.cs"), ""); File.WriteAllText(Path.Combine(project2GlobDirectory, $"2.{evaluationCount}.cs"), ""); } ); }
public void ContextCachesExistenceChecksInGetDirectoryNameOfFileAbove(EvaluationContext.SharingPolicy policy) { var context = EvaluationContext.Create(policy); var subdirectory = _env.DefaultTestDirectory.CreateDirectory("subDirectory"); var subdirectoryFile = subdirectory.CreateFile("a"); _env.DefaultTestDirectory.CreateFile("a"); int evaluationCount = 0; EvaluateProjects( new [] { $@"<Project> <PropertyGroup> <SearchedPath>$([MSBuild]::GetDirectoryNameOfFileAbove('{subdirectory.Path}', 'a'))</SearchedPath> </PropertyGroup> </Project>" }, context, project => { evaluationCount++; var searchedPath = project.GetProperty("SearchedPath"); switch (policy) { case EvaluationContext.SharingPolicy.Shared: searchedPath.EvaluatedValue.ShouldBe(subdirectory.Path); break; case EvaluationContext.SharingPolicy.Isolated: searchedPath.EvaluatedValue.ShouldBe( evaluationCount == 1 ? subdirectory.Path : _env.DefaultTestDirectory.Path); break; default: throw new ArgumentOutOfRangeException(nameof(policy), policy, null); } if (evaluationCount == 1) { // this will cause the upper file to get picked up in the Isolated policy subdirectoryFile.Delete(); } }); evaluationCount.ShouldBe(2); }
public void ContextCachesExistenceChecksInConditions(EvaluationContext.SharingPolicy policy) { var projectDirectory = _env.DefaultTestDirectory.FolderPath; _env.SetCurrentDirectory(projectDirectory); var context = EvaluationContext.Create(policy); var theFile = Path.Combine(projectDirectory, "0.cs"); File.WriteAllText(theFile, ""); var evaluationCount = 0; EvaluateProjects( _projectsWithConditions, context, project => { evaluationCount++; if (File.Exists(theFile)) { File.Delete(theFile); } if (evaluationCount == 1) { project.GetPropertyValue("p").ShouldBe("val"); } else { switch (policy) { case EvaluationContext.SharingPolicy.Shared: project.GetPropertyValue("p").ShouldBe("val"); break; case EvaluationContext.SharingPolicy.Isolated: project.GetPropertyValue("p").ShouldBeEmpty(); break; default: throw new ArgumentOutOfRangeException(nameof(policy), policy, null); } } } ); }
public static ProjectOptions CreateProjectOptionsWithResolver(SdkResolver resolver) { var context = EvaluationContext.Create(EvaluationContext.SharingPolicy.Isolated); var sdkService = (SdkResolverService)context.SdkResolverService; sdkService.InitializeForTests(null, new List <SdkResolver>() { resolver }); return(new ProjectOptions { EvaluationContext = context }); }
public void ContextDisambiguatesSameRelativeGlobsPointingInsideDifferentProjectCones(EvaluationContext.SharingPolicy policy, string[][] expectedGlobExpansions) { var projectDirectory1 = _env.DefaultTestDirectory.CreateDirectory("1").Path; var projectDirectory2 = _env.DefaultTestDirectory.CreateDirectory("2").Path; var context = EvaluationContext.Create(policy); var evaluationCount = 0; File.WriteAllText(Path.Combine(projectDirectory1, $"1.{evaluationCount}.cs"), ""); File.WriteAllText(Path.Combine(projectDirectory2, $"2.{evaluationCount}.cs"), ""); EvaluateProjects( new [] { new ProjectSpecification( Path.Combine(projectDirectory1, "1"), $@"<Project> <ItemGroup> <i Include=`{Path.Combine("**", "*.cs")}` /> </ItemGroup> </Project>"), new ProjectSpecification( Path.Combine(projectDirectory2, "2"), $@"<Project> <ItemGroup> <i Include=`{Path.Combine("**", "*.cs")}` /> </ItemGroup> </Project>"), }, context, project => { var projectName = Path.GetFileNameWithoutExtension(project.FullPath); var expectedGlobExpansion = expectedGlobExpansions[evaluationCount] .Select(i => $"{projectName}.{i}") .ToArray(); ObjectModelHelpers.AssertItems(expectedGlobExpansion, project.GetItems("i")); evaluationCount++; File.WriteAllText(Path.Combine(projectDirectory1, $"1.{evaluationCount}.cs"), ""); File.WriteAllText(Path.Combine(projectDirectory2, $"2.{evaluationCount}.cs"), ""); } ); }
public static ProjectOptions CreateProjectOptionsWithResolverFileMapping(Dictionary <string, string> mapping) { var resolver = new FileBasedMockSdkResolver(mapping); var context = EvaluationContext.Create(EvaluationContext.SharingPolicy.Isolated); var sdkService = (SdkResolverService)context.SdkResolverService; sdkService.InitializeForTests(null, new List <SdkResolver>() { resolver }); return(new ProjectOptions { EvaluationContext = context }); }
// projects should cache glob expansions when the glob is shared between projects and points outside of project cone public void ContextCachesCommonOutOfProjectConeGlob(bool itemSpecPathIsRelative, EvaluationContext.SharingPolicy policy, string[][] expectedGlobExpansions) { var testDirectory = _env.DefaultTestDirectory.FolderPath; var globDirectory = Path.Combine(testDirectory, "GlobDirectory"); var itemSpecDirectoryPart = itemSpecPathIsRelative ? Path.Combine("..", "GlobDirectory") : globDirectory; itemSpecDirectoryPart = itemSpecDirectoryPart.WithTrailingSlash(); Directory.CreateDirectory(globDirectory); // Globs with a directory part will produce items prepended with that directory part foreach (var globExpansion in expectedGlobExpansions) { for (var i = 0; i < globExpansion.Length; i++) { globExpansion[i] = Path.Combine(itemSpecDirectoryPart, globExpansion[i]); } } var projectSpecs = _projectsWithOutOfConeGlobs .Select(p => string.Format(p, itemSpecDirectoryPart)) .Select((p, i) => new ProjectSpecification(Path.Combine(testDirectory, $"ProjectDirectory{i}", $"Project{i}.proj"), p)); var context = EvaluationContext.Create(policy); var evaluationCount = 0; File.WriteAllText(Path.Combine(globDirectory, $"{evaluationCount}.cs"), ""); EvaluateProjects( projectSpecs, context, project => { var expectedGlobExpansion = expectedGlobExpansions[evaluationCount]; evaluationCount++; File.WriteAllText(Path.Combine(globDirectory, $"{evaluationCount}.cs"), ""); ObjectModelHelpers.AssertItems(expectedGlobExpansion, project.GetItems("i")); } ); }
public void ContextSdkResolverIsUsed(EvaluationContext.SharingPolicy policy, int sdkLookupsForFoo, int sdkLookupsForBar) { try { EvaluationContext.TestOnlyAlterStateOnCreate = c => SetResolverForContext(c, _resolver); var context = EvaluationContext.Create(policy); EvaluateProjects(context); _resolver.ResolvedCalls["foo"].ShouldBe(sdkLookupsForFoo); _resolver.ResolvedCalls["bar"].ShouldBe(sdkLookupsForBar); _resolver.ResolvedCalls.Count.ShouldBe(2); } finally { EvaluationContext.TestOnlyAlterStateOnCreate = null; } }
public void ContextPinsSdkResolverCache(EvaluationContext.SharingPolicy policy, int sdkLookupsForFoo, int sdkLookupsForBar) { try { EvaluationContext.TestOnlyHookOnCreate = c => SetResolverForContext(c, _resolver); var context = EvaluationContext.Create(policy); EvaluateProjects(_sdkResolutionProjects, context, null); _resolver.ResolvedCalls.Count.ShouldBe(2); _resolver.ResolvedCalls["foo"].ShouldBe(sdkLookupsForFoo); _resolver.ResolvedCalls["bar"].ShouldBe(sdkLookupsForBar); } finally { EvaluationContext.TestOnlyHookOnCreate = null; } }
public void ContextCachesImportGlobExpansions(EvaluationContext.SharingPolicy policy, string[][] expectedGlobExpansions) { var projectDirectory = _env.DefaultTestDirectory.Path; var context = EvaluationContext.Create(policy); var evaluationCount = 0; File.WriteAllText(Path.Combine(projectDirectory, $"{evaluationCount}.props"), $"<Project><ItemGroup><i Include=`{evaluationCount}.cs`/></ItemGroup></Project>".Cleanup()); EvaluateProjects( _projectsWithGlobImports, context, project => { var expectedGlobExpansion = expectedGlobExpansions[evaluationCount]; evaluationCount++; File.WriteAllText(Path.Combine(projectDirectory, $"{evaluationCount}.props"), $"<Project><ItemGroup><i Include=`{evaluationCount}.cs`/></ItemGroup></Project>".Cleanup()); ObjectModelHelpers.AssertItems(expectedGlobExpansion, project.GetItems("i")); } ); }
/// <summary> /// Recursively loads and evaluates MSBuild projects. /// </summary> /// <param name="entryProjects">An <see cref="IEnumerable{ProjectGraphEntryPoint}" /> containing the entry projects to load.</param> /// <returns>An <see cref="ICollection{ProjectWithInnerNodes}" /> object containing projects and their inner nodes if they are targeting multiple frameworks.</returns> private ICollection <ProjectWithInnerNodes> LoadProjects(IEnumerable <ProjectGraphEntryPoint> entryProjects) { var loggers = new List <Microsoft.Build.Framework.ILogger> { LoggingQueue }; // Get user specified parameters for a binary logger string binlogParameters = Environment.GetEnvironmentVariable("RESTORE_TASK_BINLOG_PARAMETERS"); // Attach the binary logger if Debug or binlog parameters were specified if (Debug || !string.IsNullOrWhiteSpace(binlogParameters)) { loggers.Add(new BinaryLogger { // Default the binlog parameters if only the debug option was specified Parameters = binlogParameters ?? "LogFile=nuget.binlog" }); } var projects = new ConcurrentDictionary <string, ProjectWithInnerNodes>(StringComparer.OrdinalIgnoreCase); var projectCollection = new ProjectCollection( globalProperties: null, // Attach a logger for evaluation only if the Debug option is set loggers: loggers, remoteLoggers: null, toolsetDefinitionLocations: ToolsetDefinitionLocations.Default, // Having more than 1 node spins up multiple msbuild.exe instances to run builds in parallel // However, these targets complete so quickly that the added overhead makes it take longer maxNodeCount: 1, onlyLogCriticalEvents: false, // Loading projects as readonly makes parsing a little faster since comments and whitespace can be ignored loadProjectsReadOnly: true); var failedBuildSubmissions = new ConcurrentBag <BuildSubmission>(); try { var sw = Stopwatch.StartNew(); var evaluationContext = EvaluationContext.Create(EvaluationContext.SharingPolicy.Shared); ProjectGraph projectGraph; int buildCount = 0; var buildParameters = new BuildParameters(projectCollection) { // Use the same loggers as the project collection Loggers = projectCollection.Loggers, LogTaskInputs = Debug }; // BeginBuild starts a queue which accepts build requests and applies the build parameters to all of them BuildManager.DefaultBuildManager.BeginBuild(buildParameters); try { // Create a ProjectGraph object and pass a factory method which creates a ProjectInstance projectGraph = new ProjectGraph(entryProjects, projectCollection, (path, properties, collection) => { var projectOptions = new ProjectOptions { EvaluationContext = evaluationContext, GlobalProperties = properties, // Ignore bad imports to maximize the chances of being able to load the project and restore LoadSettings = ProjectLoadSettings.IgnoreEmptyImports | ProjectLoadSettings.IgnoreInvalidImports | ProjectLoadSettings.IgnoreMissingImports | ProjectLoadSettings.DoNotEvaluateElementsWithFalseCondition, ProjectCollection = collection }; // Create a Project object which does the evaluation var project = Project.FromFile(path, projectOptions); // Create a ProjectInstance object which is what this factory needs to return var projectInstance = project.CreateProjectInstance(ProjectInstanceSettings.None, evaluationContext); if (!projectInstance.Targets.ContainsKey("_IsProjectRestoreSupported") || properties.TryGetValue("TargetFramework", out var targetFramework) && string.IsNullOrWhiteSpace(targetFramework)) { // In rare cases, users can set an empty TargetFramework value in a project-to-project reference. Static Graph will respect that // but NuGet does not need to do anything with that instance of the project since the actual project is still loaded correctly // with its actual TargetFramework. return(projectInstance); } // If the project supports restore, queue up a build of the 3 targets needed for restore BuildManager.DefaultBuildManager .PendBuildRequest( new BuildRequestData( projectInstance, TargetsToBuild, hostServices: null, // Suppresses an error that a target does not exist because it may or may not contain the targets that we're running BuildRequestDataFlags.SkipNonexistentTargets)) .ExecuteAsync( callback: buildSubmission => { // If the build failed, add its result to the list to be processed later if (buildSubmission.BuildResult.OverallResult == BuildResultCode.Failure) { failedBuildSubmissions.Add(buildSubmission); } }, context: null); Interlocked.Increment(ref buildCount); // Add the project instance to the list, if its an inner node for a multi-targeting project it will be added to the inner collection projects.AddOrUpdate( path, key => new ProjectWithInnerNodes(targetFramework, new MSBuildProjectInstance(projectInstance)), (_, item) => item.Add(targetFramework, new MSBuildProjectInstance(projectInstance))); return(projectInstance); }); } finally { // EndBuild blocks until all builds are complete BuildManager.DefaultBuildManager.EndBuild(); } sw.Stop(); MSBuildLogger.LogInformation(string.Format(CultureInfo.CurrentCulture, Strings.ProjectEvaluationSummary, projectGraph.ProjectNodes.Count, sw.ElapsedMilliseconds, buildCount, failedBuildSubmissions.Count)); if (failedBuildSubmissions.Any()) { // Return null if any builds failed, they will have logged errors return(null); } } catch (Exception e) { LoggingQueue.TaskLoggingHelper.LogErrorFromException(e, showStackTrace: true); return(null); } finally { projectCollection.Dispose(); } // Just return the projects not the whole dictionary as it was just used to group the projects together return(projects.Values); }