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.")
164 def get_target_build_dir(build_tool
, target
, is_iphone
=False):
166 Returns output directory absolute path dependent on build and targets.
168 r'c:\b\build\slave\win\build\src\out\Release'
169 '/mnt/data/b/build/slave/linux/build/src/out/Debug'
170 '/b/build/slave/ios_rel_device/build/src/xcodebuild/Release-iphoneos'
172 Keep this function in sync with tools/build/scripts/slave/compile.py
175 if build_tool
== 'xcode':
176 ret
= os
.path
.join(SRC_DIR
, 'xcodebuild',
177 target
+ ('-iphoneos' if is_iphone
else ''))
178 elif build_tool
in ['make', 'ninja', 'ninja-ios']: # TODO: Remove ninja-ios.
179 ret
= os
.path
.join(SRC_DIR
, 'out', target
)
180 elif build_tool
in ['msvs', 'vs', 'ib']:
181 ret
= os
.path
.join(SRC_DIR
, 'build', target
)
182 elif build_tool
== 'scons':
183 ret
= os
.path
.join(SRC_DIR
, 'sconsbuild', target
)
185 raise NotImplementedError('Unexpected GYP_GENERATORS (%s)' % build_tool
)
186 return os
.path
.abspath(ret
)
189 def set_up_landmines(target
):
190 """Does the work of setting, planting, and triggering landmines."""
191 out_dir
= get_target_build_dir(builder(), target
, platform() == 'ios')
193 landmines_path
= os
.path
.join(out_dir
, '.landmines')
194 if not os
.path
.exists(out_dir
):
197 new_landmines
= get_landmines(target
)
199 if not os
.path
.exists(landmines_path
):
200 with
open(landmines_path
, 'w') as f
:
201 f
.writelines(new_landmines
)
203 triggered
= os
.path
.join(out_dir
, '.landmines_triggered')
204 with
open(landmines_path
, 'r') as f
:
205 old_landmines
= f
.readlines()
206 if old_landmines
!= new_landmines
:
207 old_date
= time
.ctime(os
.stat(landmines_path
).st_ctime
)
208 diff
= difflib
.unified_diff(old_landmines
, new_landmines
,
209 fromfile
='old_landmines', tofile
='new_landmines',
210 fromfiledate
=old_date
, tofiledate
=time
.ctime(), n
=0)
212 with
open(triggered
, 'w') as f
:
214 elif os
.path
.exists(triggered
):
215 # Remove false triggered landmines.
220 parser
= optparse
.OptionParser()
221 parser
.add_option('-v', '--verbose', action
='store_true',
222 default
=('LANDMINES_VERBOSE' in os
.environ
),
223 help=('Emit some extra debugging information (default off). This option '
224 'is also enabled by the presence of a LANDMINES_VERBOSE environment '
226 options
, args
= parser
.parse_args()
229 parser
.error('Unknown arguments %s' % args
)
232 level
=logging
.DEBUG
if options
.verbose
else logging
.ERROR
)
234 gyp_helper
.apply_chromium_gyp_env()
236 for target
in ('Debug', 'Release', 'Debug_x64', 'Release_x64'):
237 set_up_landmines(target
)
242 if __name__
== '__main__':