/// <summary> /// Resolves the dependency names in an aggregate to NodeInfo instances, filling in the AggregateInfo.Dependenices array. Any referenced aggregates will also be linked, recursively. /// </summary> /// <param name="UnlinkedNode">The aggregate to link</param> /// <param name="NameToAggregateNode">Map of other aggregate names to their corresponding instance.</param> /// <param name="NameToBuildNode">Map from node names to their corresponding instance.</param> /// <param name="NumErrors">The number of errors output so far. Incremented if resolving this aggregate fails.</param> private static void LinkAggregate(UnlinkedAggregateNode UnlinkedNode, Dictionary <string, UnlinkedAggregateNode> NameToAggregateNode, Dictionary <string, UnlinkedBuildNode> NameToBuildNode, ref int NumErrors) { if (UnlinkedNode.Node.Dependencies == null) { UnlinkedNode.Node.Dependencies = new BuildNode[0]; HashSet <BuildNode> Dependencies = new HashSet <BuildNode>(); foreach (string DependencyName in UnlinkedNode.DependencyNames) { UnlinkedAggregateNode AggregateNodeDependency; if (NameToAggregateNode.TryGetValue(DependencyName, out AggregateNodeDependency)) { LinkAggregate(AggregateNodeDependency, NameToAggregateNode, NameToBuildNode, ref NumErrors); Dependencies.UnionWith(AggregateNodeDependency.Node.Dependencies); continue; } UnlinkedBuildNode BuildNodeDependency; if (NameToBuildNode.TryGetValue(DependencyName, out BuildNodeDependency)) { Dependencies.Add(BuildNodeDependency.Node); continue; } CommandUtils.LogError("Node {0} is not in the graph. It is a dependency of {1}.", DependencyName, UnlinkedNode.Node.Name); NumErrors++; } UnlinkedNode.Node.Dependencies = Dependencies.ToArray(); } }
/// <summary> /// Resolves the names of each node and aggregates' dependencies, and links them together into the build graph. /// </summary> /// <param name="AggregateNameToInfo">Map of aggregate names to their info objects</param> /// <param name="NodeNameToInfo">Map of node names to their info objects</param> private static void LinkGraph(IEnumerable <AggregateNodeDefinition> AggregateNodeDefinitions, IEnumerable <BuildNodeDefinition> BuildNodeDefinitions, out List <AggregateNode> AggregateNodes, out List <BuildNode> BuildNodes) { // Create all the build nodes, and a dictionary to find them by name Dictionary <string, UnlinkedBuildNode> NameToBuildNode = new Dictionary <string, UnlinkedBuildNode>(StringComparer.InvariantCultureIgnoreCase); foreach (BuildNodeDefinition Definition in BuildNodeDefinitions) { UnlinkedBuildNode UnlinkedNode = new UnlinkedBuildNode(); UnlinkedNode.InputDependencyNames = ParseSemicolonDelimitedList(Definition.DependsOn); UnlinkedNode.OrderDependencyNames = ParseSemicolonDelimitedList(Definition.RunAfter); UnlinkedNode.Node = Definition.CreateNode(); NameToBuildNode.Add(Definition.Name, UnlinkedNode); } // Create all the aggregate nodes, and add them to a dictionary too Dictionary <string, UnlinkedAggregateNode> NameToAggregateNode = new Dictionary <string, UnlinkedAggregateNode>(StringComparer.InvariantCultureIgnoreCase); foreach (AggregateNodeDefinition Definition in AggregateNodeDefinitions) { UnlinkedAggregateNode UnlinkedNode = new UnlinkedAggregateNode(); UnlinkedNode.DependencyNames = ParseSemicolonDelimitedList(Definition.DependsOn); UnlinkedNode.Node = new AggregateNode(Definition); NameToAggregateNode.Add(Definition.Name, UnlinkedNode); } // Link the graph int NumErrors = 0; foreach (UnlinkedAggregateNode Pair in NameToAggregateNode.Values) { LinkAggregate(Pair, NameToAggregateNode, NameToBuildNode, ref NumErrors); } foreach (UnlinkedBuildNode Pair in NameToBuildNode.Values) { LinkNode(Pair, new List <UnlinkedBuildNode>(), NameToAggregateNode, NameToBuildNode, ref NumErrors); } if (NumErrors > 0) { throw new AutomationException("Failed to link graph ({0} errors).", NumErrors); } // Set the output lists AggregateNodes = NameToAggregateNode.Values.Select(x => x.Node).ToList(); BuildNodes = NameToBuildNode.Values.Select(x => x.Node).ToList(); }