OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 | 2 |
3 # Copyright (c) 2009 Google Inc. All rights reserved. | 3 # Copyright (c) 2009 Google Inc. All rights reserved. |
4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
6 | 6 |
7 from compiler.ast import Const | 7 from compiler.ast import Const |
8 from compiler.ast import Dict | 8 from compiler.ast import Dict |
9 from compiler.ast import Discard | 9 from compiler.ast import Discard |
10 from compiler.ast import List | 10 from compiler.ast import List |
(...skipping 1286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1297 # If there's anything left unvisited, there must be a circular dependency | 1297 # If there's anything left unvisited, there must be a circular dependency |
1298 # (cycle). If you need to figure out what's wrong, look for elements of | 1298 # (cycle). If you need to figure out what's wrong, look for elements of |
1299 # targets that are not in flat_list. | 1299 # targets that are not in flat_list. |
1300 if len(flat_list) != len(targets): | 1300 if len(flat_list) != len(targets): |
1301 raise DependencyGraphNode.CircularException, \ | 1301 raise DependencyGraphNode.CircularException, \ |
1302 'Some targets not reachable, cycle in dependency graph detected' | 1302 'Some targets not reachable, cycle in dependency graph detected' |
1303 | 1303 |
1304 return [dependency_nodes, flat_list] | 1304 return [dependency_nodes, flat_list] |
1305 | 1305 |
1306 | 1306 |
| 1307 def VerifyNoGYPFileCircularDependencies(targets): |
| 1308 # Create a DependencyGraphNode for each gyp file containing a target. Put |
| 1309 # it into a dict for easy access. |
| 1310 dependency_nodes = {} |
| 1311 for target in targets.iterkeys(): |
| 1312 build_file = gyp.common.BuildFile(target) |
| 1313 if not build_file in dependency_nodes: |
| 1314 dependency_nodes[build_file] = DependencyGraphNode(build_file) |
| 1315 |
| 1316 # Set up the dependency links. |
| 1317 for target, spec in targets.iteritems(): |
| 1318 build_file = gyp.common.BuildFile(target) |
| 1319 build_file_node = dependency_nodes[build_file] |
| 1320 target_dependencies = spec.get('dependencies', []) |
| 1321 for dependency in target_dependencies: |
| 1322 try: |
| 1323 dependency_build_file = gyp.common.BuildFile(dependency) |
| 1324 if dependency_build_file == build_file: |
| 1325 # A .gyp file is allowed to refer back to itself. |
| 1326 continue |
| 1327 dependency_node = dependency_nodes[dependency_build_file] |
| 1328 if dependency_node not in build_file_node.dependencies: |
| 1329 build_file_node.dependencies.append(dependency_node) |
| 1330 dependency_node.dependents.append(build_file_node) |
| 1331 except KeyError, e: |
| 1332 gyp.common.ExceptionAppend( |
| 1333 e, 'while computing dependencies of .gyp file %s' % build_file) |
| 1334 raise |
| 1335 |
| 1336 # Files that have no dependencies are treated as dependent on root_node. |
| 1337 root_node = DependencyGraphNode(None) |
| 1338 for build_file_node in dependency_nodes.itervalues(): |
| 1339 if len(build_file_node.dependencies) == 0: |
| 1340 build_file_node.dependencies.append(root_node) |
| 1341 root_node.dependents.append(build_file_node) |
| 1342 |
| 1343 flat_list = root_node.FlattenToList() |
| 1344 |
| 1345 # If there's anything left unvisited, there must be a circular dependency |
| 1346 # (cycle). |
| 1347 if len(flat_list) != len(dependency_nodes): |
| 1348 bad_files = [] |
| 1349 for file in dependency_nodes.iterkeys(): |
| 1350 if not file in flat_list: |
| 1351 bad_files.append(file) |
| 1352 raise DependencyGraphNode.CircularException, \ |
| 1353 'Some files not reachable, cycle in .gyp file dependency graph ' + \ |
| 1354 'detected involving some or all of: ' + \ |
| 1355 ' '.join(bad_files) |
| 1356 |
| 1357 |
1307 def DoDependentSettings(key, flat_list, targets, dependency_nodes): | 1358 def DoDependentSettings(key, flat_list, targets, dependency_nodes): |
1308 # key should be one of all_dependent_settings, direct_dependent_settings, | 1359 # key should be one of all_dependent_settings, direct_dependent_settings, |
1309 # or link_settings. | 1360 # or link_settings. |
1310 | 1361 |
1311 for target in flat_list: | 1362 for target in flat_list: |
1312 target_dict = targets[target] | 1363 target_dict = targets[target] |
1313 build_file = gyp.common.BuildFile(target) | 1364 build_file = gyp.common.BuildFile(target) |
1314 | 1365 |
1315 if key == 'all_dependent_settings': | 1366 if key == 'all_dependent_settings': |
1316 dependencies = dependency_nodes[target].DeepDependencies() | 1367 dependencies = dependency_nodes[target].DeepDependencies() |
(...skipping 642 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1959 for index in xrange(0, len(the_list)): | 2010 for index in xrange(0, len(the_list)): |
1960 item = the_list[index] | 2011 item = the_list[index] |
1961 if isinstance(item, int): | 2012 if isinstance(item, int): |
1962 the_list[index] = str(item) | 2013 the_list[index] = str(item) |
1963 elif isinstance(item, dict): | 2014 elif isinstance(item, dict): |
1964 TurnIntIntoStrInDict(item) | 2015 TurnIntIntoStrInDict(item) |
1965 elif isinstance(item, list): | 2016 elif isinstance(item, list): |
1966 TurnIntIntoStrInList(item) | 2017 TurnIntIntoStrInList(item) |
1967 | 2018 |
1968 | 2019 |
1969 def Load(build_files, variables, includes, depth, generator_input_info, check): | 2020 def Load(build_files, variables, includes, depth, generator_input_info, check, |
| 2021 circular_check): |
1970 # Set up path_sections and non_configuration_keys with the default data plus | 2022 # Set up path_sections and non_configuration_keys with the default data plus |
1971 # the generator-specifc data. | 2023 # the generator-specifc data. |
1972 global path_sections | 2024 global path_sections |
1973 path_sections = base_path_sections[:] | 2025 path_sections = base_path_sections[:] |
1974 path_sections.extend(generator_input_info['path_sections']) | 2026 path_sections.extend(generator_input_info['path_sections']) |
1975 | 2027 |
1976 global non_configuration_keys | 2028 global non_configuration_keys |
1977 non_configuration_keys = base_non_configuration_keys[:] | 2029 non_configuration_keys = base_non_configuration_keys[:] |
1978 non_configuration_keys.extend(generator_input_info['non_configuration_keys']) | 2030 non_configuration_keys.extend(generator_input_info['non_configuration_keys']) |
1979 | 2031 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2015 | 2067 |
2016 # Build a dict to access each target's subdict by qualified name. | 2068 # Build a dict to access each target's subdict by qualified name. |
2017 targets = BuildTargetsDict(data) | 2069 targets = BuildTargetsDict(data) |
2018 | 2070 |
2019 # Fully qualify all dependency links. | 2071 # Fully qualify all dependency links. |
2020 QualifyDependencies(targets) | 2072 QualifyDependencies(targets) |
2021 | 2073 |
2022 # Expand dependencies specified as build_file:*. | 2074 # Expand dependencies specified as build_file:*. |
2023 ExpandWildcardDependencies(targets, data) | 2075 ExpandWildcardDependencies(targets, data) |
2024 | 2076 |
| 2077 if circular_check: |
| 2078 # Make sure that any targets in a.gyp don't contain dependencies in other |
| 2079 # .gyp files that further depend on a.gyp. |
| 2080 VerifyNoGYPFileCircularDependencies(targets) |
| 2081 |
2025 [dependency_nodes, flat_list] = BuildDependencyList(targets) | 2082 [dependency_nodes, flat_list] = BuildDependencyList(targets) |
2026 | 2083 |
2027 # Handle dependent settings of various types. | 2084 # Handle dependent settings of various types. |
2028 for settings_type in ['all_dependent_settings', | 2085 for settings_type in ['all_dependent_settings', |
2029 'direct_dependent_settings', | 2086 'direct_dependent_settings', |
2030 'link_settings']: | 2087 'link_settings']: |
2031 DoDependentSettings(settings_type, flat_list, targets, dependency_nodes) | 2088 DoDependentSettings(settings_type, flat_list, targets, dependency_nodes) |
2032 | 2089 |
2033 # Take out the dependent settings now that they've been published to all | 2090 # Take out the dependent settings now that they've been published to all |
2034 # of the targets that require them. | 2091 # of the targets that require them. |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2069 ValidateRunAsInTarget(target, target_dict, build_file) | 2126 ValidateRunAsInTarget(target, target_dict, build_file) |
2070 ValidateActionsInTarget(target, target_dict, build_file) | 2127 ValidateActionsInTarget(target, target_dict, build_file) |
2071 | 2128 |
2072 # Generators might not expect ints. Turn them into strs. | 2129 # Generators might not expect ints. Turn them into strs. |
2073 TurnIntIntoStrInDict(data) | 2130 TurnIntIntoStrInDict(data) |
2074 | 2131 |
2075 # TODO(mark): Return |data| for now because the generator needs a list of | 2132 # TODO(mark): Return |data| for now because the generator needs a list of |
2076 # build files that came in. In the future, maybe it should just accept | 2133 # build files that came in. In the future, maybe it should just accept |
2077 # a list, and not the whole data dict. | 2134 # a list, and not the whole data dict. |
2078 return [flat_list, targets, data] | 2135 return [flat_list, targets, data] |
OLD | NEW |