Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(42)

Side by Side Diff: scripts/slave/compile.py

Issue 1766873002: Collect failed "target"s from ninja in the compile step on Waterfall. (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/build.git@check_target_existence
Patch Set: Rebase. Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | scripts/slave/recipe_modules/chromium/api.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """A tool to build chrome, executed by buildbot. 6 """A tool to build chrome, executed by buildbot.
7 7
8 When this is run, the current directory (cwd) should be the outer build 8 When this is run, the current directory (cwd) should be the outer build
9 directory (e.g., chrome-release/build/). 9 directory (e.g., chrome-release/build/).
10 10
11 For a list of command-line options, call this script with '--help'. 11 For a list of command-line options, call this script with '--help'.
12 """ 12 """
13 13
14 import datetime 14 import datetime
15 import errno 15 import errno
16 import json
16 import multiprocessing 17 import multiprocessing
17 import optparse 18 import optparse
18 import os 19 import os
19 import re 20 import re
20 import shlex 21 import shlex
21 import sys 22 import sys
22 import time 23 import time
23 24
24 from common import chromium_utils 25 from common import chromium_utils
25 from slave import build_directory 26 from slave import build_directory
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
68 fh = sys.stdout 69 fh = sys.stdout
69 fh.write('Environment variables modified in compile.py:\n') 70 fh.write('Environment variables modified in compile.py:\n')
70 for k in sorted(list(self.overrides)): 71 for k in sorted(list(self.overrides)):
71 if k in self: 72 if k in self:
72 fh.write(' %s=%s\n' % (k, self[k])) 73 fh.write(' %s=%s\n' % (k, self[k]))
73 else: 74 else:
74 fh.write(' %s (removed)\n' % k) 75 fh.write(' %s (removed)\n' % k)
75 fh.write('\n') 76 fh.write('\n')
76 77
77 78
79 class NinjaFailedTargetCollector(object):
80 """This is to scrape the ninja output to collect failed "target"s.
81
82 A target here is actually an output node in the ninja build graph. Thus it
83 could be an object file, a lib, an executable, output of an action, etc.
84
85 When a build edge fails, its output nodes will be printed in a single line
86 in the following format these without quotes:
87 "FAILED: obj/path/to/file1.o obj/path/to/file2.o "
88 "FAILED: gen/path/to/name.cc gen/path/to/name.h "
89
90 If a target is specified in the test spec but it is not defined in the gn or
91 gyp build config, an "unknown target" error occurs in these two possible
92 formats without quotes:
93 "ninja: error: unknown target 'executable_target'"
94 "ninja: error: unknown target 'exe1', did you mean 'exe2'?"
95 """
96 NINJA_FAILURE_PREFIX = 'FAILED: '
97 NINJA_UNKNOWN_TARGET_PREFIX = 'ninja: error: unknown target '
98
99 def __init__(self, file_path):
100 self.file_path = file_path
101 self.failed_targets = []
102 self.unknown_targets = []
103 self.unrecognized_format = False
104
105 def extract(self, line):
106 if line.startswith(self.NINJA_FAILURE_PREFIX):
107 for node in line[len(self.NINJA_FAILURE_PREFIX):].split(' '):
108 node = node.strip()
109 if node:
110 self.failed_targets.append(node)
111 elif line.startswith(self.NINJA_UNKNOWN_TARGET_PREFIX):
112 parts = line[len(self.NINJA_UNKNOWN_TARGET_PREFIX):].split('\'')
113 if len(parts) >= 3 and parts[1].strip():
114 self.unknown_targets.append(parts[1].strip())
115 else:
116 self.unrecognized_format = True
117
118 def dump_as_json(self):
119 with open(self.file_path, 'wb') as f:
120 json.dump({
121 'failed_targets': self.failed_targets,
122 'unknown_targets': self.unknown_targets,
123 'unrecognized_format': self.unrecognized_format,
124 }, f)
125
126
78 def ReadHKLMValue(path, value): 127 def ReadHKLMValue(path, value):
79 """Retrieve the install path from the registry for Visual Studio 8.0 and 128 """Retrieve the install path from the registry for Visual Studio 8.0 and
80 Incredibuild.""" 129 Incredibuild."""
81 # Only available on Windows. 130 # Only available on Windows.
82 # pylint: disable=F0401 131 # pylint: disable=F0401
83 import win32api, win32con 132 import win32api, win32con
84 try: 133 try:
85 regkey = win32api.RegOpenKeyEx(win32con.HKEY_LOCAL_MACHINE, path, 0, 134 regkey = win32api.RegOpenKeyEx(win32con.HKEY_LOCAL_MACHINE, path, 0,
86 win32con.KEY_READ) 135 win32con.KEY_READ)
87 value = win32api.RegQueryValueEx(regkey, value)[0] 136 value = win32api.RegQueryValueEx(regkey, value)[0]
(...skipping 858 matching lines...) Expand 10 before | Expand all | Expand 10 after
946 ['build%d-m4' % x for x in xrange(45, 48)]): 995 ['build%d-m4' % x for x in xrange(45, 48)]):
947 return min(10 * number_of_processors, 200) 996 return min(10 * number_of_processors, 200)
948 997
949 return 50 998 return 50
950 999
951 goma_jobs = determine_goma_jobs() 1000 goma_jobs = determine_goma_jobs()
952 command.append('-j%d' % goma_jobs) 1001 command.append('-j%d' % goma_jobs)
953 1002
954 # Run the build. 1003 # Run the build.
955 env.print_overrides() 1004 env.print_overrides()
956 exit_status = chromium_utils.RunCommand(command, env=env) 1005 kwargs = {
1006 'env': env,
1007 }
1008 failed_target_collector = None
1009 if options.ninja_compile_failure:
1010 failed_target_collector = NinjaFailedTargetCollector(
1011 options.ninja_compile_failure)
1012 kwargs['parser_func'] = failed_target_collector.extract
1013 exit_status = chromium_utils.RunCommand(command, **kwargs)
957 if exit_status == 0 and options.ninja_ensure_up_to_date: 1014 if exit_status == 0 and options.ninja_ensure_up_to_date:
958 # Run the build again if we want to check that the no-op build is clean. 1015 # Run the build again if we want to check that the no-op build is clean.
959 filter_obj = EnsureUpToDateFilter() 1016 filter_obj = EnsureUpToDateFilter()
960 # Append `-d explain` to help diagnose in the failure case. 1017 # Append `-d explain` to help diagnose in the failure case.
961 command += ['-d', 'explain'] 1018 command += ['-d', 'explain']
962 chromium_utils.RunCommand(command, env=env, filter_obj=filter_obj) 1019 chromium_utils.RunCommand(command, env=env, filter_obj=filter_obj)
963 if not filter_obj.was_up_to_date: 1020 if not filter_obj.was_up_to_date:
964 print 'Failing build because ninja reported work to do.' 1021 print 'Failing build because ninja reported work to do.'
965 print 'This means that after completing a compile, another was run and' 1022 print 'This means that after completing a compile, another was run and'
966 print 'it resulted in still having work to do (that is, a no-op build' 1023 print 'it resulted in still having work to do (that is, a no-op build'
967 print 'wasn\'t a no-op). Consult the first "ninja explain:" line for a' 1024 print 'wasn\'t a no-op). Consult the first "ninja explain:" line for a'
968 print 'likely culprit.' 1025 print 'likely culprit.'
969 return 1 1026 return 1
1027 if exit_status != 0 and failed_target_collector:
1028 failed_target_collector.dump_as_json()
970 return exit_status 1029 return exit_status
971 finally: 1030 finally:
972 goma_teardown(options, env, exit_status) 1031 goma_teardown(options, env, exit_status)
973 1032
974 override_gsutil = None 1033 override_gsutil = None
975 if options.gsutil_py_path: 1034 if options.gsutil_py_path:
976 override_gsutil = [sys.executable, options.gsutil_py_path] 1035 override_gsutil = [sys.executable, options.gsutil_py_path]
977 1036
978 goma_utils.UploadNinjaLog( 1037 goma_utils.UploadNinjaLog(
979 options.target_output_dir, options.compiler, command, exit_status, 1038 options.target_output_dir, options.compiler, command, exit_status,
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after
1273 ' credentials') 1332 ' credentials')
1274 option_parser.add_option('--verbose', action='store_true') 1333 option_parser.add_option('--verbose', action='store_true')
1275 option_parser.add_option('--gsutil-py-path', 1334 option_parser.add_option('--gsutil-py-path',
1276 help='Specify path to gsutil.py script.') 1335 help='Specify path to gsutil.py script.')
1277 option_parser.add_option('--ninja-path', default='ninja', 1336 option_parser.add_option('--ninja-path', default='ninja',
1278 help='Specify path to the ninja tool.') 1337 help='Specify path to the ninja tool.')
1279 option_parser.add_option('--ninja-ensure-up-to-date', action='store_true', 1338 option_parser.add_option('--ninja-ensure-up-to-date', action='store_true',
1280 help='Checks the output of the ninja builder to ' 1339 help='Checks the output of the ninja builder to '
1281 'confirm that a second compile immediately ' 1340 'confirm that a second compile immediately '
1282 'the first is a no-op.') 1341 'the first is a no-op.')
1342 option_parser.add_option('--ninja-compile-failure',
1343 help='Specify a file to dump detailed info of '
1344 'compile failure from ninja. Effective only '
1345 'when building with ninja.')
1283 1346
1284 options, args = option_parser.parse_args() 1347 options, args = option_parser.parse_args()
1285 1348
1286 if not options.src_dir: 1349 if not options.src_dir:
1287 options.src_dir = 'src' 1350 options.src_dir = 'src'
1288 options.src_dir = os.path.abspath(options.src_dir) 1351 options.src_dir = os.path.abspath(options.src_dir)
1289 1352
1290 options.build_dir = os.path.abspath(build_directory.GetBuildOutputDirectory( 1353 options.build_dir = os.path.abspath(build_directory.GetBuildOutputDirectory(
1291 os.path.basename(options.src_dir))) 1354 os.path.basename(options.src_dir)))
1292 1355
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1351 sys.stderr.write('Unknown build tool %s.\n' % repr(options.build_tool)) 1414 sys.stderr.write('Unknown build tool %s.\n' % repr(options.build_tool))
1352 return 2 1415 return 2
1353 1416
1354 options.target_output_dir = get_target_build_dir(args, options) 1417 options.target_output_dir = get_target_build_dir(args, options)
1355 1418
1356 return main(options, args) 1419 return main(options, args)
1357 1420
1358 1421
1359 if '__main__' == __name__: 1422 if '__main__' == __name__:
1360 sys.exit(real_main()) 1423 sys.exit(real_main())
OLDNEW
« no previous file with comments | « no previous file | scripts/slave/recipe_modules/chromium/api.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698