blob: 857585adbfa6b84bf2ccf07d4c4e2aedd9f4592e [file] [log] [blame]
iannucci@chromium.orgdccbcf12012-11-14 13:59:48 +09001#!/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"""
iannucci@chromium.orgdccbcf12012-11-14 13:59:48 +09007This 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
iannucci@chromium.orgb48a6382012-11-15 11:53:03 +090018import logging
19import optparse
iannucci@chromium.orgdccbcf12012-11-14 13:59:48 +090020import os
iannucci@chromium.orgdccbcf12012-11-14 13:59:48 +090021import sys
sivachandra@chromium.org54da9682013-08-21 11:44:58 +090022import subprocess
iannucci@chromium.orgdccbcf12012-11-14 13:59:48 +090023import time
24
sivachandra@chromium.org54da9682013-08-21 11:44:58 +090025import landmine_utils
26
27
iannucci@chromium.orgdccbcf12012-11-14 13:59:48 +090028SRC_DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
29
iannucci@chromium.orgdccbcf12012-11-14 13:59:48 +090030
31def get_target_build_dir(build_tool, target, is_iphone=False):
32 """
33 Returns output directory absolute path dependent on build and targets.
34 Examples:
35 r'c:\b\build\slave\win\build\src\out\Release'
36 '/mnt/data/b/build/slave/linux/build/src/out/Debug'
37 '/b/build/slave/ios_rel_device/build/src/xcodebuild/Release-iphoneos'
38
39 Keep this function in sync with tools/build/scripts/slave/compile.py
40 """
41 ret = None
42 if build_tool == 'xcode':
43 ret = os.path.join(SRC_DIR, 'xcodebuild',
44 target + ('-iphoneos' if is_iphone else ''))
thakis@chromium.orgcf894a72013-05-12 04:13:21 +090045 elif build_tool in ['make', 'ninja', 'ninja-ios']: # TODO: Remove ninja-ios.
iannucci@chromium.orgdccbcf12012-11-14 13:59:48 +090046 ret = os.path.join(SRC_DIR, 'out', target)
iannucci@chromium.orgf2710aa2012-11-15 10:52:07 +090047 elif build_tool in ['msvs', 'vs', 'ib']:
iannucci@chromium.orgdccbcf12012-11-14 13:59:48 +090048 ret = os.path.join(SRC_DIR, 'build', target)
iannucci@chromium.orgdccbcf12012-11-14 13:59:48 +090049 else:
scottmg@chromium.org39465182013-01-18 08:50:02 +090050 raise NotImplementedError('Unexpected GYP_GENERATORS (%s)' % build_tool)
iannucci@chromium.orgdccbcf12012-11-14 13:59:48 +090051 return os.path.abspath(ret)
52
53
sivachandra@chromium.org54da9682013-08-21 11:44:58 +090054def set_up_landmines(target, new_landmines):
iannucci@chromium.orgb48a6382012-11-15 11:53:03 +090055 """Does the work of setting, planting, and triggering landmines."""
sivachandra@chromium.org54da9682013-08-21 11:44:58 +090056 out_dir = get_target_build_dir(landmine_utils.builder(), target,
57 landmine_utils.platform() == 'ios')
iannucci@chromium.orgb48a6382012-11-15 11:53:03 +090058
59 landmines_path = os.path.join(out_dir, '.landmines')
60 if not os.path.exists(out_dir):
61 os.makedirs(out_dir)
62
iannucci@chromium.orgb48a6382012-11-15 11:53:03 +090063 if not os.path.exists(landmines_path):
64 with open(landmines_path, 'w') as f:
65 f.writelines(new_landmines)
66 else:
67 triggered = os.path.join(out_dir, '.landmines_triggered')
68 with open(landmines_path, 'r') as f:
69 old_landmines = f.readlines()
70 if old_landmines != new_landmines:
71 old_date = time.ctime(os.stat(landmines_path).st_ctime)
72 diff = difflib.unified_diff(old_landmines, new_landmines,
73 fromfile='old_landmines', tofile='new_landmines',
74 fromfiledate=old_date, tofiledate=time.ctime(), n=0)
75
76 with open(triggered, 'w') as f:
77 f.writelines(diff)
78 elif os.path.exists(triggered):
79 # Remove false triggered landmines.
80 os.remove(triggered)
81
82
tkent@chromium.org05c93a72013-09-03 06:51:18 +090083def process_options():
84 """Returns a list of landmine emitting scripts."""
iannucci@chromium.orgb48a6382012-11-15 11:53:03 +090085 parser = optparse.OptionParser()
sivachandra@chromium.org54da9682013-08-21 11:44:58 +090086 parser.add_option(
87 '-s', '--landmine-scripts', action='append',
88 default=[os.path.join(SRC_DIR, 'build', 'get_landmines.py')],
89 help='Path to the script which emits landmines to stdout. The target '
tkent@chromium.org05c93a72013-09-03 06:51:18 +090090 'is passed to this script via option -t. Note that an extra '
91 'script can be specified via an env var EXTRA_LANDMINES_SCRIPT.')
iannucci@chromium.orgb48a6382012-11-15 11:53:03 +090092 parser.add_option('-v', '--verbose', action='store_true',
93 default=('LANDMINES_VERBOSE' in os.environ),
94 help=('Emit some extra debugging information (default off). This option '
95 'is also enabled by the presence of a LANDMINES_VERBOSE environment '
96 'variable.'))
sivachandra@chromium.org54da9682013-08-21 11:44:58 +090097
iannucci@chromium.orgb48a6382012-11-15 11:53:03 +090098 options, args = parser.parse_args()
99
100 if args:
101 parser.error('Unknown arguments %s' % args)
102
103 logging.basicConfig(
104 level=logging.DEBUG if options.verbose else logging.ERROR)
iannucci@chromium.orgdccbcf12012-11-14 13:59:48 +0900105
tkent@chromium.org05c93a72013-09-03 06:51:18 +0900106 extra_script = os.environ.get('EXTRA_LANDMINES_SCRIPT')
107 if extra_script:
108 return options.landmine_scripts + [extra_script]
109 else:
110 return options.landmine_scripts
111
112
113def main():
114 landmine_scripts = process_options()
scottmg@chromium.org87ca2792014-02-15 14:23:29 +0900115
116 if landmine_utils.builder() == 'dump_dependency_json':
117 return 0
iannucci@chromium.orgdccbcf12012-11-14 13:59:48 +0900118
iannucci@chromium.org7cfb1542013-03-30 06:17:44 +0900119 for target in ('Debug', 'Release', 'Debug_x64', 'Release_x64'):
sivachandra@chromium.org54da9682013-08-21 11:44:58 +0900120 landmines = []
tkent@chromium.org05c93a72013-09-03 06:51:18 +0900121 for s in landmine_scripts:
sivachandra@chromium.org54da9682013-08-21 11:44:58 +0900122 proc = subprocess.Popen([sys.executable, s, '-t', target],
123 stdout=subprocess.PIPE)
124 output, _ = proc.communicate()
125 landmines.extend([('%s\n' % l.strip()) for l in output.splitlines()])
126 set_up_landmines(target, landmines)
iannucci@chromium.orgdccbcf12012-11-14 13:59:48 +0900127
128 return 0
129
130
131if __name__ == '__main__':
iannucci@chromium.orgb48a6382012-11-15 11:53:03 +0900132 sys.exit(main())