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.
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
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"""
36 @functools.wraps(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])
50 return sys
.platform
in ['win32', 'cygwin']
55 return sys
.platform
.startswith('linux')
60 return sys
.platform
== 'darwin'
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 def gyp_msvs_version():
71 return os
.environ
.get('GYP_MSVS_VERSION', '')
76 Returns a string which is the distributed build engine in use (if any).
77 Possible values: 'goma', 'ib', ''
79 if 'goma' in gyp_defines():
82 if 'CHROME_HEADLESS' in os
.environ
:
83 return 'ib' # use (win and !goma and headless) as approximation of ib
89 Returns a string representing the platform this build is targetted for.
90 Possible values: 'win', 'mac', 'linux', 'ios', 'android'
92 if 'OS' in gyp_defines():
93 if 'android' in gyp_defines()['OS']:
96 return gyp_defines()['OS']
108 Returns a string representing the build engine (not compiler) to use.
109 Possible values: 'make', 'ninja', 'xcode', 'msvs', 'scons'
111 if 'GYP_GENERATORS' in os
.environ
:
112 # for simplicity, only support the first explicit generator
113 generator
= os
.environ
['GYP_GENERATORS'].split(',')[0]
114 if generator
.endswith('-android'):
115 return generator
.split('-')[0]
116 elif generator
.endswith('-ninja'):
121 if platform() == 'android':
122 # Good enough for now? Do any android bots use make?
124 elif platform() == 'ios':
133 assert False, 'Don\'t know what builder we\'re using!'
136 def get_landmines(target
):
138 ALL LANDMINES ARE DEFINED HERE.
139 target is 'Release' or 'Debug'
142 add
= lambda item
: landmines
.append(item
+ '\n')
144 if (distributor() == 'goma' and platform() == 'win32' and
145 builder() == 'ninja'):
146 add('Need to clobber winja goma due to backend cwd cache fix.')
147 if platform() == 'android':
148 add('Clobber: Resources removed in r195014 require clobber.')
149 if platform() == 'win' and builder() == 'ninja':
150 add('Compile on cc_unittests fails due to symbols removed in r185063.')
151 if platform() == 'linux' and builder() == 'ninja':
152 add('Builders switching from make to ninja will clobber on this.')
153 if platform() == 'mac':
154 add('Switching from bundle to unbundled dylib (issue 14743002).')
155 if (platform() == 'win' and builder() == 'ninja' and
156 gyp_msvs_version() == '2012' and
157 gyp_defines().get('target_arch') == 'x64' and
158 gyp_defines().get('dcheck_always_on') == '1'):
159 add("Switched win x64 trybots from VS2010 to VS2012.")
160 add('Need to clobber everything due to an IDL change in r154579 (blink)')
165 def get_target_build_dir(build_tool
, target
, is_iphone
=False):
167 Returns output directory absolute path dependent on build and targets.
169 r'c:\b\build\slave\win\build\src\out\Release'
170 '/mnt/data/b/build/slave/linux/build/src/out/Debug'
171 '/b/build/slave/ios_rel_device/build/src/xcodebuild/Release-iphoneos'
173 Keep this function in sync with tools/build/scripts/slave/compile.py
176 if build_tool
== 'xcode':
177 ret
= os
.path
.join(SRC_DIR
, 'xcodebuild',
178 target
+ ('-iphoneos' if is_iphone
else ''))
179 elif build_tool
in ['make', 'ninja', 'ninja-ios']: # TODO: Remove ninja-ios.
180 ret
= os
.path
.join(SRC_DIR
, 'out', target
)
181 elif build_tool
in ['msvs', 'vs', 'ib']:
182 ret
= os
.path
.join(SRC_DIR
, 'build', target
)
183 elif build_tool
== 'scons':
184 ret
= os
.path
.join(SRC_DIR
, 'sconsbuild', target
)
186 raise NotImplementedError('Unexpected GYP_GENERATORS (%s)' % build_tool
)
187 return os
.path
.abspath(ret
)
190 def set_up_landmines(target
):
191 """Does the work of setting, planting, and triggering landmines."""
192 out_dir
= get_target_build_dir(builder(), target
, platform() == 'ios')
194 landmines_path
= os
.path
.join(out_dir
, '.landmines')
195 if not os
.path
.exists(out_dir
):
198 new_landmines
= get_landmines(target
)
200 if not os
.path
.exists(landmines_path
):
201 with
open(landmines_path
, 'w') as f
:
202 f
.writelines(new_landmines
)
204 triggered
= os
.path
.join(out_dir
, '.landmines_triggered')
205 with
open(landmines_path
, 'r') as f
:
206 old_landmines
= f
.readlines()
207 if old_landmines
!= new_landmines
:
208 old_date
= time
.ctime(os
.stat(landmines_path
).st_ctime
)
209 diff
= difflib
.unified_diff(old_landmines
, new_landmines
,
210 fromfile
='old_landmines', tofile
='new_landmines',
211 fromfiledate
=old_date
, tofiledate
=time
.ctime(), n
=0)
213 with
open(triggered
, 'w') as f
:
215 elif os
.path
.exists(triggered
):
216 # Remove false triggered landmines.
221 parser
= optparse
.OptionParser()
222 parser
.add_option('-v', '--verbose', action
='store_true',
223 default
=('LANDMINES_VERBOSE' in os
.environ
),
224 help=('Emit some extra debugging information (default off). This option '
225 'is also enabled by the presence of a LANDMINES_VERBOSE environment '
227 options
, args
= parser
.parse_args()
230 parser
.error('Unknown arguments %s' % args
)
233 level
=logging
.DEBUG
if options
.verbose
else logging
.ERROR
)
235 gyp_helper
.apply_chromium_gyp_env()
237 for target
in ('Debug', 'Release', 'Debug_x64', 'Release_x64'):
238 set_up_landmines(target
)
243 if __name__
== '__main__':