| Index: pylib/gyp/input.py
|
| ===================================================================
|
| --- pylib/gyp/input.py (revision 784)
|
| +++ pylib/gyp/input.py (working copy)
|
| @@ -1304,6 +1304,57 @@
|
| return [dependency_nodes, flat_list]
|
|
|
|
|
| +def VerifyNoGYPFileCircularDependencies(targets):
|
| + # Create a DependencyGraphNode for each gyp file containing a target. Put
|
| + # it into a dict for easy access.
|
| + dependency_nodes = {}
|
| + for target in targets.iterkeys():
|
| + build_file = gyp.common.BuildFile(target)
|
| + if not build_file in dependency_nodes:
|
| + dependency_nodes[build_file] = DependencyGraphNode(build_file)
|
| +
|
| + # Set up the dependency links.
|
| + for target, spec in targets.iteritems():
|
| + build_file = gyp.common.BuildFile(target)
|
| + build_file_node = dependency_nodes[build_file]
|
| + target_dependencies = spec.get('dependencies', [])
|
| + for dependency in target_dependencies:
|
| + try:
|
| + dependency_build_file = gyp.common.BuildFile(dependency)
|
| + if dependency_build_file == build_file:
|
| + # A .gyp file is allowed to refer back to itself.
|
| + continue
|
| + dependency_node = dependency_nodes[dependency_build_file]
|
| + if dependency_node not in build_file_node.dependencies:
|
| + build_file_node.dependencies.append(dependency_node)
|
| + dependency_node.dependents.append(build_file_node)
|
| + except KeyError, e:
|
| + gyp.common.ExceptionAppend(
|
| + e, 'while computing dependencies of .gyp file %s' % build_file)
|
| + raise
|
| +
|
| + # Files that have no dependencies are treated as dependent on root_node.
|
| + root_node = DependencyGraphNode(None)
|
| + for build_file_node in dependency_nodes.itervalues():
|
| + if len(build_file_node.dependencies) == 0:
|
| + build_file_node.dependencies.append(root_node)
|
| + root_node.dependents.append(build_file_node)
|
| +
|
| + flat_list = root_node.FlattenToList()
|
| +
|
| + # If there's anything left unvisited, there must be a circular dependency
|
| + # (cycle).
|
| + if len(flat_list) != len(dependency_nodes):
|
| + bad_files = []
|
| + for file in dependency_nodes.iterkeys():
|
| + if not file in flat_list:
|
| + bad_files.append(file)
|
| + raise DependencyGraphNode.CircularException, \
|
| + 'Some files not reachable, cycle in .gyp file dependency graph ' + \
|
| + 'detected involving some or all of: ' + \
|
| + ' '.join(bad_files)
|
| +
|
| +
|
| def DoDependentSettings(key, flat_list, targets, dependency_nodes):
|
| # key should be one of all_dependent_settings, direct_dependent_settings,
|
| # or link_settings.
|
| @@ -1966,7 +2017,8 @@
|
| TurnIntIntoStrInList(item)
|
|
|
|
|
| -def Load(build_files, variables, includes, depth, generator_input_info, check):
|
| +def Load(build_files, variables, includes, depth, generator_input_info, check,
|
| + circular_check):
|
| # Set up path_sections and non_configuration_keys with the default data plus
|
| # the generator-specifc data.
|
| global path_sections
|
| @@ -2022,6 +2074,11 @@
|
| # Expand dependencies specified as build_file:*.
|
| ExpandWildcardDependencies(targets, data)
|
|
|
| + if circular_check:
|
| + # Make sure that any targets in a.gyp don't contain dependencies in other
|
| + # .gyp files that further depend on a.gyp.
|
| + VerifyNoGYPFileCircularDependencies(targets)
|
| +
|
| [dependency_nodes, flat_list] = BuildDependencyList(targets)
|
|
|
| # Handle dependent settings of various types.
|
|
|