blob: 220b8a7989f45cd7a037473be6db65b70d2551b4 [file] [log] [blame]
[email protected]abab8d72012-11-14 04:59:481#!/usr/bin/env python
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
4# found in the LICENSE file.
5
6"""
[email protected]abab8d72012-11-14 04:59:487This script runs every build as a hook. If it detects that the build should
8be clobbered, it will touch the file <build_dir>/.landmine_triggered. The
9various build scripts will then check for the presence of this file and clobber
10accordingly. The script will also emit the reasons for the clobber to stdout.
11
12A landmine is tripped when a builder checks out a different revision, and the
13diff between the new landmines and the old ones is non-null. At this point, the
14build is clobbered.
15"""
16
17import difflib
[email protected]d99e6bf2014-04-23 04:19:2318import errno
[email protected]c45227b2012-11-15 02:53:0319import logging
20import optparse
[email protected]abab8d72012-11-14 04:59:4821import os
[email protected]abab8d72012-11-14 04:59:4822import sys
[email protected]ec069f72013-08-21 02:44:5823import subprocess
[email protected]abab8d72012-11-14 04:59:4824import time
25
[email protected]ec069f72013-08-21 02:44:5826import landmine_utils
27
28
[email protected]abab8d72012-11-14 04:59:4829SRC_DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
30
[email protected]abab8d72012-11-14 04:59:4831
32def get_target_build_dir(build_tool, target, is_iphone=False):
33 """
34 Returns output directory absolute path dependent on build and targets.
35 Examples:
36 r'c:\b\build\slave\win\build\src\out\Release'
37 '/mnt/data/b/build/slave/linux/build/src/out/Debug'
38 '/b/build/slave/ios_rel_device/build/src/xcodebuild/Release-iphoneos'
39
40 Keep this function in sync with tools/build/scripts/slave/compile.py
41 """
42 ret = None
43 if build_tool == 'xcode':
44 ret = os.path.join(SRC_DIR, 'xcodebuild',
45 target + ('-iphoneos' if is_iphone else ''))
[email protected]ddca2f72013-05-11 19:13:2146 elif build_tool in ['make', 'ninja', 'ninja-ios']: # TODO: Remove ninja-ios.
[email protected]abab8d72012-11-14 04:59:4847 ret = os.path.join(SRC_DIR, 'out', target)
[email protected]d074d472012-11-15 01:52:0748 elif build_tool in ['msvs', 'vs', 'ib']:
[email protected]abab8d72012-11-14 04:59:4849 ret = os.path.join(SRC_DIR, 'build', target)
[email protected]abab8d72012-11-14 04:59:4850 else:
[email protected]68d80692013-01-17 23:50:0251 raise NotImplementedError('Unexpected GYP_GENERATORS (%s)' % build_tool)
[email protected]abab8d72012-11-14 04:59:4852 return os.path.abspath(ret)
53
54
[email protected]ec069f72013-08-21 02:44:5855def set_up_landmines(target, new_landmines):
[email protected]c45227b2012-11-15 02:53:0356 """Does the work of setting, planting, and triggering landmines."""
[email protected]ec069f72013-08-21 02:44:5857 out_dir = get_target_build_dir(landmine_utils.builder(), target,
58 landmine_utils.platform() == 'ios')
[email protected]c45227b2012-11-15 02:53:0359
60 landmines_path = os.path.join(out_dir, '.landmines')
[email protected]d99e6bf2014-04-23 04:19:2361 try:
[email protected]c45227b2012-11-15 02:53:0362 os.makedirs(out_dir)
[email protected]d99e6bf2014-04-23 04:19:2363 except OSError as e:
64 if e.errno == errno.EEXIST:
65 pass
[email protected]c45227b2012-11-15 02:53:0366
[email protected]f3d0d1c32014-05-22 22:12:4867 if os.path.exists(landmines_path):
[email protected]c45227b2012-11-15 02:53:0368 triggered = os.path.join(out_dir, '.landmines_triggered')
69 with open(landmines_path, 'r') as f:
70 old_landmines = f.readlines()
71 if old_landmines != new_landmines:
72 old_date = time.ctime(os.stat(landmines_path).st_ctime)
73 diff = difflib.unified_diff(old_landmines, new_landmines,
74 fromfile='old_landmines', tofile='new_landmines',
75 fromfiledate=old_date, tofiledate=time.ctime(), n=0)
76
77 with open(triggered, 'w') as f:
78 f.writelines(diff)
79 elif os.path.exists(triggered):
80 # Remove false triggered landmines.
81 os.remove(triggered)
[email protected]f3d0d1c32014-05-22 22:12:4882 with open(landmines_path, 'w') as f:
83 f.writelines(new_landmines)
[email protected]c45227b2012-11-15 02:53:0384
85
[email protected]c36d62932013-09-02 21:51:1886def process_options():
87 """Returns a list of landmine emitting scripts."""
[email protected]c45227b2012-11-15 02:53:0388 parser = optparse.OptionParser()
[email protected]ec069f72013-08-21 02:44:5889 parser.add_option(
90 '-s', '--landmine-scripts', action='append',
91 default=[os.path.join(SRC_DIR, 'build', 'get_landmines.py')],
92 help='Path to the script which emits landmines to stdout. The target '
[email protected]c36d62932013-09-02 21:51:1893 'is passed to this script via option -t. Note that an extra '
94 'script can be specified via an env var EXTRA_LANDMINES_SCRIPT.')
[email protected]c45227b2012-11-15 02:53:0395 parser.add_option('-v', '--verbose', action='store_true',
96 default=('LANDMINES_VERBOSE' in os.environ),
97 help=('Emit some extra debugging information (default off). This option '
98 'is also enabled by the presence of a LANDMINES_VERBOSE environment '
99 'variable.'))
[email protected]ec069f72013-08-21 02:44:58100
[email protected]c45227b2012-11-15 02:53:03101 options, args = parser.parse_args()
102
103 if args:
104 parser.error('Unknown arguments %s' % args)
105
106 logging.basicConfig(
107 level=logging.DEBUG if options.verbose else logging.ERROR)
[email protected]abab8d72012-11-14 04:59:48108
[email protected]c36d62932013-09-02 21:51:18109 extra_script = os.environ.get('EXTRA_LANDMINES_SCRIPT')
110 if extra_script:
111 return options.landmine_scripts + [extra_script]
112 else:
113 return options.landmine_scripts
114
115
116def main():
117 landmine_scripts = process_options()
[email protected]07e55632014-02-15 05:23:29118
[email protected]a403a3d2014-04-12 01:13:21119 if landmine_utils.builder() in ('dump_dependency_json', 'eclipse'):
[email protected]07e55632014-02-15 05:23:29120 return 0
[email protected]abab8d72012-11-14 04:59:48121
[email protected]31e8a852013-03-29 21:17:44122 for target in ('Debug', 'Release', 'Debug_x64', 'Release_x64'):
[email protected]ec069f72013-08-21 02:44:58123 landmines = []
[email protected]c36d62932013-09-02 21:51:18124 for s in landmine_scripts:
[email protected]ec069f72013-08-21 02:44:58125 proc = subprocess.Popen([sys.executable, s, '-t', target],
126 stdout=subprocess.PIPE)
127 output, _ = proc.communicate()
128 landmines.extend([('%s\n' % l.strip()) for l in output.splitlines()])
129 set_up_landmines(target, landmines)
[email protected]abab8d72012-11-14 04:59:48130
131 return 0
132
133
134if __name__ == '__main__':
[email protected]c45227b2012-11-15 02:53:03135 sys.exit(main())