Index: tools/determinism/compare_build_artifacts.py |
diff --git a/tools/determinism/compare_build_artifacts.py b/tools/determinism/compare_build_artifacts.py |
index 9a3bb9345a220b4db84e1d993f19290b33a00760..769e73abb1c5f63c07fead8ff85cce3172a3b05a 100755 |
--- a/tools/determinism/compare_build_artifacts.py |
+++ b/tools/determinism/compare_build_artifacts.py |
@@ -9,7 +9,10 @@ import difflib |
import json |
import optparse |
import os |
+import re |
+import shutil |
import struct |
+import subprocess |
import sys |
import time |
@@ -495,6 +498,67 @@ def compare_files(first_filepath, second_filepath): |
return diff_binary(first_filepath, second_filepath, file_len) |
+def get_deps(build_dir, target): |
+ """Returns list of object files needed to build target.""" |
+ NODE_PATTERN = re.compile(r'label="([a-zA-Z0-9_\\/.-]+)"') |
+ CHECK_EXTS = ('.o', '.obj') |
+ |
+ # Rename to possibly original directory name if possible. |
+ fixed_build_dir = build_dir |
+ if build_dir.endswith('.1') or build_dir.endswith('.2'): |
+ fixed_build_dir = build_dir[:-2] |
+ if os.path.exists(fixed_build_dir): |
+ print >> sys.stderr, ('fixed_build_dir %s exists.' |
+ ' will try to use orig dir.' % fixed_build_dir) |
+ fixed_build_dir = build_dir |
+ else: |
+ shutil.move(build_dir, fixed_build_dir) |
+ |
+ try: |
+ out = subprocess.check_output(['ninja', '-C', fixed_build_dir, |
+ '-t', 'graph', target]) |
+ except subprocess.CalledProcessError as e: |
+ print >> sys.stderr, 'error to get graph for %s: %s' % (target, e) |
+ return [] |
+ |
+ finally: |
+ # Rename again if we renamed before. |
+ if fixed_build_dir != build_dir: |
+ shutil.move(fixed_build_dir, build_dir) |
+ |
+ files = [] |
+ for line in out.splitlines(): |
+ matched = NODE_PATTERN.search(line) |
+ if matched: |
+ path = matched.group(1) |
+ if not os.path.splitext(path)[1] in CHECK_EXTS: |
+ continue |
+ if os.path.isabs(path): |
+ print >> sys.stderr, ('not support abs path %s used for target %s' |
+ % (path, target)) |
+ continue |
+ files.append(path) |
+ return files |
+ |
+ |
+def compare_deps(first_dir, second_dir, targets): |
+ """Print difference of dependent files.""" |
+ for target in targets: |
+ print 'Checking %s difference:' % target |
+ first_deps = get_deps(first_dir, target) |
+ second_deps =get_deps(second_dir, target) |
+ if set(first_deps) != set(second_deps): |
+ # Since we do not thiks this case occur, we do not do anything special |
+ # for this case. |
+ print 'deps on %s are different: %s' % ( |
+ target, set(first_deps).symmetric_difference(set(second_deps))) |
+ continue |
+ for d in first_deps: |
+ first_file = os.path.join(first_dir, d) |
+ second_file = os.path.join(second_dir, d) |
+ compare_files(first_file, second_file) |
+ |
+ |
def compare_build_artifacts(first_dir, second_dir, target_platform, |
recursive=False): |
"""Compares the artifacts from two distinct builds.""" |
@@ -561,6 +625,11 @@ def compare_build_artifacts(first_dir, second_dir, target_platform, |
for u in unexpected_equals: |
print(' %s' % u) |
+ if unexpected_diffs: |
+ diffs_to_investigate = set(unexpected_diffs).difference( |
+ set(missing_files)) |
+ compare_deps(first_dir, second_dir, diffs_to_investigate) |
+ |
return int(bool(unexpected_diffs)) |