Index: pylib/gyp/generator/analyzer.py |
=================================================================== |
--- pylib/gyp/generator/analyzer.py (revision 1961) |
+++ pylib/gyp/generator/analyzer.py (working copy) |
@@ -64,6 +64,12 @@ |
'CONFIGURATION_NAME']: |
generator_default_variables[unused] = '' |
+def _ToGypPath(path): |
scottmg
2014/08/05 23:02:43
I don't understand why some functions are _ and so
sky
2014/08/06 00:26:07
Indeed. Python sites recommend __, which is why I
|
+ """Converts a path to the format used by gyp.""" |
+ if os.sep == '\\' and os.altsep == '/': |
+ return path.replace('\\', '/') |
+ return path |
+ |
def __ExtractBasePath(target): |
"""Extracts the path components of the specified gyp target path.""" |
last_index = target.rfind('/') |
@@ -120,10 +126,7 @@ |
# |target| is either absolute or relative and in the format of the OS. Gyp |
# source paths are always posix. Convert |target| to a posix path relative to |
# |toplevel_dir_|. This is done to make it easy to build source paths. |
- if os.sep == '\\' and os.altsep == '/': |
- base_path = target.replace('\\', '/') |
- else: |
- base_path = target |
+ base_path = _ToGypPath(target) |
if base_path == toplevel_dir: |
base_path = '' |
elif base_path.startswith(toplevel_dir + '/'): |
@@ -216,7 +219,30 @@ |
except IOError: |
raise Exception('Unable to open file', file_path) |
-def __GenerateTargets(target_list, target_dicts, toplevel_dir, files): |
+def _WasBuildFileModified(build_file, data, files): |
+ """Returns true if the build file |build_file| is either in |files| or |
+ one of the files included by |build_file| is in |files|.""" |
+ if _ToGypPath(build_file) in files: |
+ if debug: |
+ print 'gyp file modified', build_file |
+ return True |
+ |
+ # First element of included_files is the file itself. |
+ if len(data[build_file]['included_files']) <= 1: |
+ return False |
+ |
+ for include_file in data[build_file]['included_files'][1:]: |
+ # |included_files| are relative to the directory of the |build_file|. |
+ rel_include_file = \ |
+ _ToGypPath(gyp.common.UnrelativePath(include_file, build_file)) |
+ if rel_include_file in files: |
+ if debug: |
+ print 'included gyp file modified, gyp_file=', build_file, \ |
+ 'included file=', rel_include_file |
+ return True |
+ return False |
+ |
+def __GenerateTargets(data, target_list, target_dicts, toplevel_dir, files): |
"""Generates a dictionary with the key the name of a target and the value a |
Target. |toplevel_dir| is the root of the source tree. If the sources of |
a target match that of |files|, then |target.matched| is set to True. |
@@ -229,6 +255,10 @@ |
matched = False |
+ # Maps from build file to a boolean indicating whether the build file is in |
+ # |files|. |
+ build_file_in_files = {} |
+ |
while len(targets_to_visit) > 0: |
target_name = targets_to_visit.pop() |
if target_name in targets: |
@@ -236,14 +266,26 @@ |
target = Target() |
targets[target_name] = target |
- sources = __ExtractSources(target_name, target_dicts[target_name], |
- toplevel_dir) |
- for source in sources: |
- if source in files: |
- target.match_status = MATCH_STATUS_MATCHES |
- matched = True |
- break |
+ build_file = gyp.common.ParseQualifiedTarget(target_name)[0] |
+ if not build_file in build_file_in_files: |
+ build_file_in_files[build_file] = \ |
+ _WasBuildFileModified(build_file, data, files) |
+ |
+ # 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]: |
+ target.match_status = MATCH_STATUS_MATCHES |
+ matched = True |
+ else: |
+ sources = __ExtractSources(target_name, target_dicts[target_name], |
+ toplevel_dir) |
+ for source in sources: |
+ if source in files: |
+ target.match_status = MATCH_STATUS_MATCHES |
+ matched = True |
+ break |
+ |
for dep in target_dicts[target_name].get('dependencies', []): |
targets[target_name].deps.add(dep) |
targets_to_visit.append(dep) |
@@ -345,23 +387,38 @@ |
raise Exception('Must specify files to analyze via config_path generator ' |
'flag') |
- toplevel_dir = os.path.abspath(params['options'].toplevel_dir) |
- if os.sep == '\\' and os.altsep == '/': |
- toplevel_dir = toplevel_dir.replace('\\', '/') |
+ toplevel_dir = _ToGypPath(os.path.abspath(params['options'].toplevel_dir)) |
if debug: |
print 'toplevel_dir', toplevel_dir |
- all_targets, matched = __GenerateTargets(target_list, target_dicts, |
- toplevel_dir, |
- frozenset(config.files)) |
+ matched = False |
+ matched_include = False |
+ # If one of the modified files is an include file then everything is |
+ # effected. |
scottmg
2014/08/05 23:02:43
nit; affected.
sky
2014/08/06 00:26:07
I ALWAYS get that wrong.
|
+ if params['options'].includes: |
+ for include in params['options'].includes: |
+ if _ToGypPath(include) in config.files: |
+ if debug: |
+ print 'include path modified', include |
+ matched_include = True |
+ matched = True |
+ break |
+ |
+ if not matched: |
+ all_targets, matched = __GenerateTargets(data, target_list, target_dicts, |
+ toplevel_dir, |
+ frozenset(config.files)) |
+ |
# Set of targets that refer to one of the files. |
if config.look_for_dependency_only: |
print found_dependency_string if matched else no_dependency_string |
return |
warning = None |
- if matched: |
+ if matched_include: |
+ output_targets = config.targets |
+ elif matched: |
unqualified_mapping = _GetUnqualifiedToQualifiedMapping( |
all_targets, config.targets) |
if len(unqualified_mapping) != len(config.targets): |