| Index: pylib/gyp/generator/analyzer.py
|
| diff --git a/pylib/gyp/generator/analyzer.py b/pylib/gyp/generator/analyzer.py
|
| index f403d4e266b048e59b81512ad43c2a95e37dcc74..0e01e9c811e287e90d9d07f5e7b293ec65f0cdf9 100644
|
| --- a/pylib/gyp/generator/analyzer.py
|
| +++ b/pylib/gyp/generator/analyzer.py
|
| @@ -11,17 +11,32 @@ targets: list of targets to search for. The target names are unqualified.
|
|
|
| The following is output:
|
| error: only supplied if there is an error.
|
| -targets: the set of targets passed in via targets that either directly or
|
| - indirectly depend upon the set of paths supplied in files.
|
| build_targets: minimal set of targets that directly depend on the changed
|
| files and need to be built. The expectation is this set of targets is passed
|
| - into a build step.
|
| + into a build step. The returned values are either values in the supplied
|
| + targets, or have a dependency on one of the supplied targets.
|
| status: outputs one of three values: none of the supplied files were found,
|
| one of the include files changed so that it should be assumed everything
|
| changed (in this case targets and build_targets are not output) or at
|
| least one file was found.
|
| invalid_targets: list of supplied targets thare were not found.
|
|
|
| +Example:
|
| +Consider a graph like the following:
|
| + A D
|
| + / \
|
| +B C
|
| +A depends upon both B and C, A is of type none and B and C are executables.
|
| +D is an executable, has no dependencies and nothing depends on it.
|
| +If |targets| = ["A"] and files = ["b.cc", "d.cc"] (B depends upon b.cc and D
|
| +depends upon d.cc), then the following is output:
|
| +|build_targets| = ["B"] B must built as it depends upon the changed file b.cc
|
| +and the supplied target A depends upon it. A is not output as a build_target
|
| +as it is of type none with no rules and actions.
|
| +
|
| +Even though the file d.cc, which D depends upon, has changed D is not output
|
| +as none of the supplied targets (A) depend upon D.
|
| +
|
| If the generator flag analyzer_output_path is specified, output is written
|
| there. Otherwise output is written to stdout.
|
| """
|
| @@ -259,13 +274,12 @@ def _WasBuildFileModified(build_file, data, files, toplevel_dir):
|
|
|
| def _GetOrCreateTargetByName(targets, target_name):
|
| """Creates or returns the Target at targets[target_name]. If there is no
|
| - Target for |target_name| one is created. Returns a tuple of whether a new
|
| - Target was created and the Target."""
|
| + Target for |target_name| one is created."""
|
| if target_name in targets:
|
| - return False, targets[target_name]
|
| + return targets[target_name]
|
| target = Target(target_name)
|
| targets[target_name] = target
|
| - return True, target
|
| + return target
|
|
|
|
|
| def _DoesTargetTypeRequireBuild(target_dict):
|
| @@ -280,7 +294,6 @@ def _GenerateTargets(data, target_list, target_dicts, toplevel_dir, files,
|
| """Returns a tuple of the following:
|
| . A dictionary mapping from fully qualified name to Target.
|
| . A list of the targets that have a source file in |files|.
|
| - . Set of root Targets reachable from the the files |build_files|.
|
| This sets the |match_status| of the targets that contain any of the source
|
| files in |files| to MATCH_STATUS_MATCHES.
|
| |toplevel_dir| is the root of the source tree."""
|
| @@ -297,18 +310,10 @@ def _GenerateTargets(data, target_list, target_dicts, toplevel_dir, files,
|
| # |files|.
|
| build_file_in_files = {}
|
|
|
| - # Root targets across all files.
|
| - roots = set()
|
| -
|
| - # Set of Targets in |build_files|.
|
| - build_file_targets = set()
|
| -
|
| while len(targets_to_visit) > 0:
|
| target_name = targets_to_visit.pop()
|
| - created_target, target = _GetOrCreateTargetByName(targets, target_name)
|
| - if created_target:
|
| - roots.add(target)
|
| - elif target.visited:
|
| + target = _GetOrCreateTargetByName(targets, target_name)
|
| + if target.visited:
|
| continue
|
|
|
| target.visited = True
|
| @@ -325,9 +330,6 @@ def _GenerateTargets(data, target_list, target_dicts, toplevel_dir, files,
|
| build_file_in_files[build_file] = \
|
| _WasBuildFileModified(build_file, data, files, toplevel_dir)
|
|
|
| - if build_file in build_files:
|
| - build_file_targets.add(target)
|
| -
|
| # If a build file (or any of its included files) is modified we assume all
|
| # targets in the file are modified.
|
| if build_file_in_files[build_file]:
|
| @@ -348,14 +350,12 @@ def _GenerateTargets(data, target_list, target_dicts, toplevel_dir, files,
|
| for dep in target_dicts[target_name].get('dependencies', []):
|
| targets_to_visit.append(dep)
|
|
|
| - created_dep_target, dep_target = _GetOrCreateTargetByName(targets, dep)
|
| - if not created_dep_target:
|
| - roots.discard(dep_target)
|
| + dep_target = _GetOrCreateTargetByName(targets, dep)
|
|
|
| target.deps.add(dep_target)
|
| dep_target.back_deps.add(target)
|
|
|
| - return targets, matching_targets, roots & build_file_targets
|
| + return targets, matching_targets
|
|
|
|
|
| def _GetUnqualifiedToTargetMapping(all_targets, to_find):
|
| @@ -375,51 +375,19 @@ def _GetUnqualifiedToTargetMapping(all_targets, to_find):
|
| return result
|
|
|
|
|
| -def _DoesTargetDependOn(target):
|
| - """Returns true if |target| or any of its dependencies matches the supplied
|
| - set of paths. This updates |matches| of the Targets as it recurses.
|
| - target: the Target to look for."""
|
| - if target.match_status == MATCH_STATUS_DOESNT_MATCH:
|
| - return False
|
| - if target.match_status == MATCH_STATUS_MATCHES or \
|
| - target.match_status == MATCH_STATUS_MATCHES_BY_DEPENDENCY:
|
| - return True
|
| - for dep in target.deps:
|
| - if _DoesTargetDependOn(dep):
|
| - target.match_status = MATCH_STATUS_MATCHES_BY_DEPENDENCY
|
| - print '\t', target.name, 'matches by dep', dep.name
|
| - return True
|
| - target.match_status = MATCH_STATUS_DOESNT_MATCH
|
| - return False
|
| -
|
| -
|
| -def _GetTargetsDependingOn(possible_targets):
|
| - """Returns the list of Targets in |possible_targets| that depend (either
|
| - directly on indirectly) on the matched targets.
|
| - possible_targets: targets to search from."""
|
| - found = []
|
| - print 'Targets that matched by dependency:'
|
| - for target in possible_targets:
|
| - if _DoesTargetDependOn(target):
|
| - found.append(target)
|
| - return found
|
| -
|
| -
|
| -def _AddBuildTargets(target, roots, add_if_no_ancestor, result):
|
| +def _AddBuildTargets(target, roots, result):
|
| """Recurses through all targets that depend on |target|, adding all targets
|
| that need to be built (and are in |roots|) to |result|.
|
| roots: set of root targets.
|
| - add_if_no_ancestor: If true and there are no ancestors of |target| then add
|
| - |target| to |result|. |target| must still be in |roots|.
|
| result: targets that need to be built are added here."""
|
| if target.visited:
|
| return
|
|
|
| target.visited = True
|
| - target.in_roots = not target.back_deps and target in roots
|
| + target.in_roots = target in roots
|
|
|
| for back_dep_target in target.back_deps:
|
| - _AddBuildTargets(back_dep_target, roots, False, result)
|
| + _AddBuildTargets(back_dep_target, roots, result)
|
| target.added_to_compile_targets |= back_dep_target.added_to_compile_targets
|
| target.in_roots |= back_dep_target.in_roots
|
| target.is_or_has_linked_ancestor |= (
|
| @@ -433,16 +401,14 @@ def _AddBuildTargets(target, roots, add_if_no_ancestor, result):
|
| # static libraries themselves, which are not compile time dependencies.
|
| if target.in_roots and \
|
| (target.is_executable or
|
| - (not target.added_to_compile_targets and
|
| - (add_if_no_ancestor or target.requires_build)) or
|
| - (target.is_static_library and add_if_no_ancestor and
|
| - not target.is_or_has_linked_ancestor)):
|
| + (not target.added_to_compile_targets and target.requires_build) or
|
| + (target.is_static_library and not target.is_or_has_linked_ancestor)):
|
| print '\t\tadding to build targets', target.name, 'executable', \
|
| target.is_executable, 'added_to_compile_targets', \
|
| - target.added_to_compile_targets, 'add_if_no_ancestor', \
|
| - add_if_no_ancestor, 'requires_build', target.requires_build, \
|
| - 'is_static_library', target.is_static_library, \
|
| - 'is_or_has_linked_ancestor', target.is_or_has_linked_ancestor
|
| + target.added_to_compile_targets, 'requires_build', \
|
| + target.requires_build, 'is_static_library', \
|
| + target.is_static_library, 'is_or_has_linked_ancestor', \
|
| + target.is_or_has_linked_ancestor
|
| result.add(target)
|
| target.added_to_compile_targets = True
|
|
|
| @@ -454,7 +420,7 @@ def _GetBuildTargets(matching_targets, roots):
|
| result = set()
|
| for target in matching_targets:
|
| print '\tfinding build targets for match', target.name
|
| - _AddBuildTargets(target, roots, True, result)
|
| + _AddBuildTargets(target, roots, result)
|
| return result
|
|
|
|
|
| @@ -557,14 +523,10 @@ def GenerateOutput(target_list, target_dicts, data, params):
|
| _WriteOutput(params, **result_dict)
|
| return
|
|
|
| - all_targets, matching_targets, roots = _GenerateTargets(
|
| + all_targets, matching_targets = _GenerateTargets(
|
| data, target_list, target_dicts, toplevel_dir, frozenset(config.files),
|
| params['build_files'])
|
|
|
| - print 'roots:'
|
| - for root in roots:
|
| - print '\t', root.name
|
| -
|
| unqualified_mapping = _GetUnqualifiedToTargetMapping(all_targets,
|
| config.targets)
|
| invalid_targets = None
|
| @@ -579,24 +541,18 @@ def GenerateOutput(target_list, target_dicts, data, params):
|
| print 'expanded supplied targets'
|
| for target in search_targets:
|
| print '\t', target.name
|
| - matched_search_targets = _GetTargetsDependingOn(search_targets)
|
| - print 'raw matched search targets:'
|
| - for target in matched_search_targets:
|
| - print '\t', target.name
|
| # Reset the visited status for _GetBuildTargets.
|
| for target in all_targets.itervalues():
|
| target.visited = False
|
| print 'Finding build targets'
|
| - build_targets = _GetBuildTargets(matching_targets, roots)
|
| - matched_search_targets = [gyp.common.ParseQualifiedTarget(target.name)[1]
|
| - for target in matched_search_targets]
|
| + build_targets = _GetBuildTargets(matching_targets, search_targets)
|
| build_targets = [gyp.common.ParseQualifiedTarget(target.name)[1]
|
| for target in build_targets]
|
| else:
|
| - matched_search_targets = []
|
| build_targets = []
|
|
|
| - result_dict = { 'targets': matched_search_targets,
|
| + # TODO(sky): nuke 'targets'.
|
| + result_dict = { 'targets': build_targets,
|
| 'status': found_dependency_string if matching_targets else
|
| no_dependency_string,
|
| 'build_targets': build_targets}
|
|
|