Fix callback after destruction of native ContentViewRenderView.
[chromium-blink-merge.git] / build / landmines.py
blob40177eadd7affdce00bab46e38fd9696f55ed25e
1 #!/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.
6 """
7 This file holds a list of reasons why a particular build needs to be clobbered
8 (or a list of 'landmines').
10 This script runs every build as a hook. If it detects that the build should
11 be clobbered, it will touch the file <build_dir>/.landmine_triggered. The
12 various build scripts will then check for the presence of this file and clobber
13 accordingly. The script will also emit the reasons for the clobber to stdout.
15 A landmine is tripped when a builder checks out a different revision, and the
16 diff between the new landmines and the old ones is non-null. At this point, the
17 build is clobbered.
18 """
20 import difflib
21 import functools
22 import gyp_helper
23 import logging
24 import optparse
25 import os
26 import shlex
27 import sys
28 import time
30 SRC_DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
32 def memoize(default=None):
33 """This decorator caches the return value of a parameterless pure function"""
34 def memoizer(func):
35 val = []
36 @functools.wraps(func)
37 def inner():
38 if not val:
39 ret = func()
40 val.append(ret if ret is not None else default)
41 if logging.getLogger().isEnabledFor(logging.INFO):
42 print '%s -> %r' % (func.__name__, val[0])
43 return val[0]
44 return inner
45 return memoizer
48 @memoize()
49 def IsWindows():
50 return sys.platform in ['win32', 'cygwin']
53 @memoize()
54 def IsLinux():
55 return sys.platform.startswith('linux')
58 @memoize()
59 def IsMac():
60 return sys.platform == 'darwin'
63 @memoize()
64 def gyp_defines():
65 """Parses and returns GYP_DEFINES env var as a dictionary."""
66 return dict(arg.split('=', 1)
67 for arg in shlex.split(os.environ.get('GYP_DEFINES', '')))
70 @memoize()
71 def distributor():
72 """
73 Returns a string which is the distributed build engine in use (if any).
74 Possible values: 'goma', 'ib', ''
75 """
76 if 'goma' in gyp_defines():
77 return 'goma'
78 elif IsWindows():
79 if 'CHROME_HEADLESS' in os.environ:
80 return 'ib' # use (win and !goma and headless) as approximation of ib
83 @memoize()
84 def platform():
85 """
86 Returns a string representing the platform this build is targetted for.
87 Possible values: 'win', 'mac', 'linux', 'ios', 'android'
88 """
89 if 'OS' in gyp_defines():
90 if 'android' in gyp_defines()['OS']:
91 return 'android'
92 else:
93 return gyp_defines()['OS']
94 elif IsWindows():
95 return 'win'
96 elif IsLinux():
97 return 'linux'
98 else:
99 return 'mac'
102 @memoize()
103 def builder():
105 Returns a string representing the build engine (not compiler) to use.
106 Possible values: 'make', 'ninja', 'xcode', 'msvs', 'scons'
108 if 'GYP_GENERATORS' in os.environ:
109 # for simplicity, only support the first explicit generator
110 generator = os.environ['GYP_GENERATORS'].split(',')[0]
111 if generator.endswith('-android'):
112 return generator.split('-')[0]
113 elif generator.endswith('-ninja'):
114 return 'ninja'
115 else:
116 return generator
117 else:
118 if platform() == 'android':
119 # Good enough for now? Do any android bots use make?
120 return 'ninja'
121 elif platform() == 'ios':
122 return 'xcode'
123 elif IsWindows():
124 return 'msvs'
125 elif IsLinux():
126 return 'ninja'
127 elif IsMac():
128 return 'xcode'
129 else:
130 assert False, 'Don\'t know what builder we\'re using!'
133 def get_landmines(target):
135 ALL LANDMINES ARE DEFINED HERE.
136 target is 'Release' or 'Debug'
138 landmines = []
139 add = lambda item: landmines.append(item + '\n')
141 if (distributor() == 'goma' and platform() == 'win32' and
142 builder() == 'ninja'):
143 add('Need to clobber winja goma due to backend cwd cache fix.')
144 if platform() == 'android':
145 add('Clobber: Resources removed in r195014 require clobber.')
146 if platform() == 'win' and builder() == 'ninja':
147 add('Compile on cc_unittests fails due to symbols removed in r185063.')
148 if platform() == 'linux' and builder() == 'ninja':
149 add('Builders switching from make to ninja will clobber on this.')
150 if platform() == 'mac':
151 add('Switching from bundle to unbundled dylib (issue 14743002).')
153 return landmines
156 def get_target_build_dir(build_tool, target, is_iphone=False):
158 Returns output directory absolute path dependent on build and targets.
159 Examples:
160 r'c:\b\build\slave\win\build\src\out\Release'
161 '/mnt/data/b/build/slave/linux/build/src/out/Debug'
162 '/b/build/slave/ios_rel_device/build/src/xcodebuild/Release-iphoneos'
164 Keep this function in sync with tools/build/scripts/slave/compile.py
166 ret = None
167 if build_tool == 'xcode':
168 ret = os.path.join(SRC_DIR, 'xcodebuild',
169 target + ('-iphoneos' if is_iphone else ''))
170 elif build_tool in ['make', 'ninja', 'ninja-ios']: # TODO: Remove ninja-ios.
171 ret = os.path.join(SRC_DIR, 'out', target)
172 elif build_tool in ['msvs', 'vs', 'ib']:
173 ret = os.path.join(SRC_DIR, 'build', target)
174 elif build_tool == 'scons':
175 ret = os.path.join(SRC_DIR, 'sconsbuild', target)
176 else:
177 raise NotImplementedError('Unexpected GYP_GENERATORS (%s)' % build_tool)
178 return os.path.abspath(ret)
181 def set_up_landmines(target):
182 """Does the work of setting, planting, and triggering landmines."""
183 out_dir = get_target_build_dir(builder(), target, platform() == 'ios')
185 landmines_path = os.path.join(out_dir, '.landmines')
186 if not os.path.exists(out_dir):
187 os.makedirs(out_dir)
189 new_landmines = get_landmines(target)
191 if not os.path.exists(landmines_path):
192 with open(landmines_path, 'w') as f:
193 f.writelines(new_landmines)
194 else:
195 triggered = os.path.join(out_dir, '.landmines_triggered')
196 with open(landmines_path, 'r') as f:
197 old_landmines = f.readlines()
198 if old_landmines != new_landmines:
199 old_date = time.ctime(os.stat(landmines_path).st_ctime)
200 diff = difflib.unified_diff(old_landmines, new_landmines,
201 fromfile='old_landmines', tofile='new_landmines',
202 fromfiledate=old_date, tofiledate=time.ctime(), n=0)
204 with open(triggered, 'w') as f:
205 f.writelines(diff)
206 elif os.path.exists(triggered):
207 # Remove false triggered landmines.
208 os.remove(triggered)
211 def main():
212 parser = optparse.OptionParser()
213 parser.add_option('-v', '--verbose', action='store_true',
214 default=('LANDMINES_VERBOSE' in os.environ),
215 help=('Emit some extra debugging information (default off). This option '
216 'is also enabled by the presence of a LANDMINES_VERBOSE environment '
217 'variable.'))
218 options, args = parser.parse_args()
220 if args:
221 parser.error('Unknown arguments %s' % args)
223 logging.basicConfig(
224 level=logging.DEBUG if options.verbose else logging.ERROR)
226 gyp_helper.apply_chromium_gyp_env()
228 for target in ('Debug', 'Release', 'Debug_x64', 'Release_x64'):
229 set_up_landmines(target)
231 return 0
234 if __name__ == '__main__':
235 sys.exit(main())