OLD | NEW |
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 |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
108 | 108 |
109 if cc: | 109 if cc: |
110 print 'Forcing CC = %s' % cc | 110 print 'Forcing CC = %s' % cc |
111 env['CC'] = cc | 111 env['CC'] = cc |
112 | 112 |
113 if ldplusplus: | 113 if ldplusplus: |
114 print 'Forcing LDPLUSPLUS = %s' % ldplusplus | 114 print 'Forcing LDPLUSPLUS = %s' % ldplusplus |
115 env['LDPLUSPLUS'] = ldplusplus | 115 env['LDPLUSPLUS'] = ldplusplus |
116 | 116 |
117 | 117 |
| 118 class CombineFilter(chromium_utils.RunCommandFilter): |
| 119 """A RunCommandFilter that runs several RunCommandFilters in a sequence.""" |
| 120 def __init__(self, *filters): |
| 121 chromium_utils.RunCommandFilter.__init__(self) |
| 122 self.filters = filter(None, filters) |
| 123 |
| 124 def FilterLine(self, a_line): |
| 125 """Called by RunCommand for each line of output.""" |
| 126 for f in self.filters: a_line = f.FilterLine(a_line) |
| 127 return a_line |
| 128 |
| 129 def FilterDone(self, last_bits): |
| 130 """Called by RunCommand when the command is done.""" |
| 131 for f in self.filters: last_bits = f.FilterDone(last_bits) |
| 132 return last_bits |
| 133 |
| 134 |
| 135 # clang uses ANSII escape codes for colored diagnostics. Sadly, they get |
| 136 # disabled when ninja is used (https://github.com/martine/ninja/issues/174), |
| 137 # so we force clang's colors on. This filters the escape codes out so that |
| 138 # they don't show up on the buildbot output. |
| 139 # TODO(thakis): Pass escape sequences on to the master, and strip them there. |
| 140 # Then they can be converted to html on the side. |
| 141 class AnsiiEscapeSequenceStripper(chromium_utils.RunCommandFilter): |
| 142 # http://en.wikipedia.org/wiki/ANSI_escape_code#Sequence_elements |
| 143 # Only strip CSIs. |
| 144 # This regex was taken from colorama. |
| 145 ANSI_RE = re.compile('\033\[(?:\d|;)*[a-zA-Z]') |
| 146 |
| 147 def FilterLine(self, a_line): |
| 148 """Called by RunCommand for each line of output.""" |
| 149 return AnsiiEscapeSequenceStripper.ANSI_RE.sub('', a_line) |
| 150 |
| 151 def FilterDone(self, last_bits): |
| 152 """Called by RunCommand when the command is done.""" |
| 153 return AnsiiEscapeSequenceStripper.ANSI_RE.sub('', last_bits) |
| 154 |
| 155 |
118 # RunCommandFilter for xcodebuild | 156 # RunCommandFilter for xcodebuild |
119 class XcodebuildFilter(chromium_utils.RunCommandFilter): | 157 class XcodebuildFilter(chromium_utils.RunCommandFilter): |
120 """xcodebuild filter""" | 158 """xcodebuild filter""" |
121 | 159 |
122 # This isn't a full on state machine because there are some builds that | 160 # This isn't a full on state machine because there are some builds that |
123 # invoke xcodebuild as part of a target action. Instead it relies on | 161 # invoke xcodebuild as part of a target action. Instead it relies on |
124 # the consistent format that Xcode uses for its steps. The output follows | 162 # the consistent format that Xcode uses for its steps. The output follows |
125 # the pattern of: | 163 # the pattern of: |
126 # 1. a section line for the target | 164 # 1. a section line for the target |
127 # 2. a "header" for each thing done (Compile, PhaseScriptExecution, etc.) | 165 # 2. a "header" for each thing done (Compile, PhaseScriptExecution, etc.) |
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
356 | 394 |
357 env = EchoDict(os.environ) | 395 env = EchoDict(os.environ) |
358 common_xcode_settings(command, options, env, options.compiler) | 396 common_xcode_settings(command, options, env, options.compiler) |
359 | 397 |
360 # Add on any remaining args | 398 # Add on any remaining args |
361 command.extend(args) | 399 command.extend(args) |
362 | 400 |
363 # Set up the filter before changing directories so the raw build log can | 401 # Set up the filter before changing directories so the raw build log can |
364 # be recorded. | 402 # be recorded. |
365 # Support a local file blocking filters (for debugging). Also check the | 403 # Support a local file blocking filters (for debugging). Also check the |
366 # darwin version to make sure this is not 10.5 (easier then checking the | 404 # darwin version to make sure this is not 10.5 (easier than checking the |
367 # Xcode version), as Xcode 3.1.x has slightly different output. | 405 # Xcode version), as Xcode 3.1.x has slightly different output. |
368 xcodebuild_filter = None | 406 xcodebuild_filter = None |
369 no_filter_path = os.path.join(os.getcwd(), 'no_xcodebuild_filter') | 407 no_filter_path = os.path.join(os.getcwd(), 'no_xcodebuild_filter') |
370 if os.path.exists(no_filter_path): | 408 if os.path.exists(no_filter_path): |
371 print 'NOTE: "%s" exists, output is unfiltered' % no_filter_path | 409 print 'NOTE: "%s" exists, output is unfiltered' % no_filter_path |
372 elif os.uname()[3].startswith('Darwin Kernel Version 9.'): | 410 elif os.uname()[3].startswith('Darwin Kernel Version 9.'): |
373 print 'NOTE: Filtering output not supported on Mac OS X 10.5' | 411 print 'NOTE: Filtering output not supported on Mac OS X 10.5' |
374 else: | 412 else: |
375 full_log_path = os.path.join(os.getcwd(), 'full_xcodebuild_log.txt') | 413 full_log_path = os.path.join(os.getcwd(), 'full_xcodebuild_log.txt') |
376 full_log = open(full_log_path, 'w') | 414 full_log = open(full_log_path, 'w') |
(...skipping 13 matching lines...) Expand all Loading... |
390 env['GOMA_COMPILER_PROXY_DAEMON_MODE'] = 'true' | 428 env['GOMA_COMPILER_PROXY_DAEMON_MODE'] = 'true' |
391 if os.path.exists(goma_key): | 429 if os.path.exists(goma_key): |
392 env['GOMA_API_KEY_FILE'] = goma_key | 430 env['GOMA_API_KEY_FILE'] = goma_key |
393 if options.clobber: | 431 if options.clobber: |
394 chromium_utils.RunCommand(goma_ctl_cmd + ['restart'], env=env) | 432 chromium_utils.RunCommand(goma_ctl_cmd + ['restart'], env=env) |
395 else: | 433 else: |
396 chromium_utils.RunCommand(goma_ctl_cmd + ['ensure_start'], env=env) | 434 chromium_utils.RunCommand(goma_ctl_cmd + ['ensure_start'], env=env) |
397 | 435 |
398 # Run the build. | 436 # Run the build. |
399 env.print_overrides() | 437 env.print_overrides() |
| 438 |
| 439 filter_obj = AnsiiEscapeSequenceStripper() |
| 440 if xcodebuild_filter: |
| 441 filter_obj = CombineFilter(filter_obj, xcodebuild_filter) |
400 result = chromium_utils.RunCommand(command, env=env, | 442 result = chromium_utils.RunCommand(command, env=env, |
401 filter_obj=xcodebuild_filter) | 443 filter_obj=filter_obj) |
402 | 444 |
403 if options.compiler in ('goma', 'goma-clang', 'gomaclang'): | 445 if options.compiler in ('goma', 'goma-clang', 'gomaclang'): |
404 # Always stop the proxy for now to allow in-place update. | 446 # Always stop the proxy for now to allow in-place update. |
405 chromium_utils.RunCommand(goma_ctl_cmd + ['stop'], env=env) | 447 chromium_utils.RunCommand(goma_ctl_cmd + ['stop'], env=env) |
406 | 448 |
407 return result | 449 return result |
408 | 450 |
409 | 451 |
410 DISTRIBUTION_FILE = '/etc/lsb-release' | 452 DISTRIBUTION_FILE = '/etc/lsb-release' |
411 def get_ubuntu_codename(): | 453 def get_ubuntu_codename(): |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
636 goma_key = os.path.join(options.goma_dir, 'goma.key') | 678 goma_key = os.path.join(options.goma_dir, 'goma.key') |
637 env['GOMA_COMPILER_PROXY_DAEMON_MODE'] = 'true' | 679 env['GOMA_COMPILER_PROXY_DAEMON_MODE'] = 'true' |
638 if os.path.exists(goma_key): | 680 if os.path.exists(goma_key): |
639 env['GOMA_API_KEY_FILE'] = goma_key | 681 env['GOMA_API_KEY_FILE'] = goma_key |
640 if options.clobber: | 682 if options.clobber: |
641 chromium_utils.RunCommand(goma_ctl_cmd + ['restart'], env=env) | 683 chromium_utils.RunCommand(goma_ctl_cmd + ['restart'], env=env) |
642 else: | 684 else: |
643 chromium_utils.RunCommand(goma_ctl_cmd + ['ensure_start'], env=env) | 685 chromium_utils.RunCommand(goma_ctl_cmd + ['ensure_start'], env=env) |
644 | 686 |
645 # Run the build. | 687 # Run the build. |
| 688 filter_obj = None |
| 689 if options.compiler in ('clang', 'goma-clang'): |
| 690 filter_obj = AnsiiEscapeSequenceStripper() |
646 env.print_overrides() | 691 env.print_overrides() |
647 result = chromium_utils.RunCommand(command, env=env) | 692 result = chromium_utils.RunCommand(command, env=env, |
| 693 filter_obj=filter_obj) |
648 | 694 |
649 if options.compiler in ('goma', 'goma-clang'): | 695 if options.compiler in ('goma', 'goma-clang'): |
650 # Always stop the proxy for now to allow in-place update. | 696 # Always stop the proxy for now to allow in-place update. |
651 chromium_utils.RunCommand(goma_ctl_cmd + ['stop'], env=env) | 697 chromium_utils.RunCommand(goma_ctl_cmd + ['stop'], env=env) |
652 | 698 |
653 return result | 699 return result |
654 | 700 |
655 | 701 |
656 def main_scons(options, args): | 702 def main_scons(options, args): |
657 """Interprets options, clobbers object files, and calls scons. | 703 """Interprets options, clobbers object files, and calls scons. |
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
966 main = build_tool_map.get(options.build_tool) | 1012 main = build_tool_map.get(options.build_tool) |
967 if not main: | 1013 if not main: |
968 sys.stderr.write('Unknown build tool %s.\n' % repr(options.build_tool)) | 1014 sys.stderr.write('Unknown build tool %s.\n' % repr(options.build_tool)) |
969 return 2 | 1015 return 2 |
970 | 1016 |
971 return main(options, args) | 1017 return main(options, args) |
972 | 1018 |
973 | 1019 |
974 if '__main__' == __name__: | 1020 if '__main__' == __name__: |
975 sys.exit(real_main()) | 1021 sys.exit(real_main()) |
OLD | NEW |