/// <summary> /// Constructs a graph starting from the given graph entry points, evaluating with the provided project collection. /// </summary> /// <param name="entryPoints">The entry points to use in constructing the graph</param> /// <param name="projectCollection"> /// The collection with which all projects in the graph should be associated. May not be /// null. /// </param> /// <param name="projectInstanceFactory"> /// A delegate used for constructing a <see cref="ProjectInstance" />, called for each /// project created during graph creation. This value can be null, which uses /// a default implementation that calls the ProjectInstance constructor. See the remarks /// on <see cref="ProjectInstanceFactoryFunc" /> for other scenarios. /// </param> /// <param name="degreeOfParallelism"> /// Number of threads to participate in building the project graph. /// </param> /// <param name="cancellationToken"> /// The <see cref="T:System.Threading.CancellationToken" /> token to observe. /// </param> /// <exception cref="InvalidProjectFileException"> /// If the evaluation of any project in the graph fails /// </exception> /// <exception cref="InvalidOperationException"> /// If a null reference is returned from <paramref name="projectInstanceFactory" /> /// </exception> /// <exception cref="CircularDependencyException"> /// If the evaluation is successful but the project graph contains a circular /// dependency /// </exception> public ProjectGraph( IEnumerable <ProjectGraphEntryPoint> entryPoints, ProjectCollection projectCollection, ProjectInstanceFactoryFunc projectInstanceFactory, int degreeOfParallelism, CancellationToken cancellationToken) { ErrorUtilities.VerifyThrowArgumentNull(projectCollection, nameof(projectCollection)); projectInstanceFactory = projectInstanceFactory ?? DefaultProjectInstanceFactory; var graphBuilder = new GraphBuilder( entryPoints, projectCollection, projectInstanceFactory, ProjectInterpretation.Instance, degreeOfParallelism, cancellationToken); graphBuilder.BuildGraph(); EntryPointNodes = graphBuilder.EntryPointNodes; GraphRoots = graphBuilder.RootNodes; ProjectNodes = graphBuilder.ProjectNodes; Edges = graphBuilder.Edges; _projectNodesTopologicallySorted = new Lazy <IReadOnlyCollection <ProjectGraphNode> >(() => TopologicalSort(GraphRoots, ProjectNodes)); }
public ProjectGraph( IEnumerable <ProjectGraphEntryPoint> entryPoints, ProjectCollection projectCollection, ProjectInstanceFactoryFunc projectInstanceFactory, int degreeOfParallelism, CancellationToken cancellationToken) { ErrorUtilities.VerifyThrowArgumentNull(projectCollection, nameof(projectCollection)); var measurementInfo = BeginMeasurement(); projectInstanceFactory ??= DefaultProjectInstanceFactory; var graphBuilder = new GraphBuilder( entryPoints, projectCollection, projectInstanceFactory, ProjectInterpretation.Instance, degreeOfParallelism, cancellationToken); graphBuilder.BuildGraph(); EntryPointNodes = graphBuilder.EntryPointNodes; GraphRoots = graphBuilder.RootNodes; ProjectNodes = graphBuilder.ProjectNodes; Edges = graphBuilder.Edges; _projectNodesTopologicallySorted = new Lazy <IReadOnlyCollection <ProjectGraphNode> >(() => TopologicalSort(GraphRoots, ProjectNodes)); ConstructionMetrics = EndMeasurement(); (Stopwatch Timer, string ETWArgs) BeginMeasurement() { string etwArgs = null; if (MSBuildEventSource.Log.IsEnabled()) { etwArgs = string.Join(";", entryPoints.Select( e => { var globalPropertyString = e.GlobalProperties == null ? string.Empty : string.Join(", ", e.GlobalProperties.Select(kvp => $"{kvp.Key} = {kvp.Value}")); return($"{e.ProjectFile}({globalPropertyString})"); })); MSBuildEventSource.Log.ProjectGraphConstructionStart(etwArgs); } return(Stopwatch.StartNew(), etwArgs); } GraphConstructionMetrics EndMeasurement() { if (MSBuildEventSource.Log.IsEnabled()) { MSBuildEventSource.Log.ProjectGraphConstructionStop(measurementInfo.ETWArgs); } measurementInfo.Timer.Stop(); return(new GraphConstructionMetrics( measurementInfo.Timer.Elapsed, ProjectNodes.Count, Edges.Count)); } }