Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(887)

Side by Side Diff: build/landmines.py

Issue 11175016: Selective build clobbering feature (landmines.py and android build scripts). (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: fix nits Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« build/gyp_helper.py ('K') | « build/gyp_helper.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.
5
6 """
7 This file holds a list of reasons why a particular build needs to be clobbered
8 (or a list of 'landmines').
9
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.
14
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 """
19
20 import difflib
21 import functools
22 import gyp_helper
23 import os
24 import shlex
25 import sys
26 import time
27
28
29 def memoize(default=None):
30 """This decorator caches the return value of a parameterless pure function"""
31 def memoizer(func):
32 val = []
33 @functools.wraps(func)
34 def inner(*args, **kwargs):
35 if not val:
36 ret = func(*args, **kwargs)
37 val.append(ret if ret is not None else default)
38 print '%s -> %r' % (func.__name__, val[0])
39 return val[0]
40 return inner
41 return memoizer
42
43
44 @memoize()
45 def IsWindows():
46 return sys.platform.startswith('win') or sys.platform == 'cygwin'
47
48
49 @memoize()
50 def IsLinux():
51 return sys.platform.startswith('linux')
52
53
54 @memoize()
55 def IsMac():
56 return sys.platform.startswith('darwin')
57
58
59 @memoize()
60 def gyp_defines():
61 return dict(arg.split('=', 1)
62 for arg in shlex.split(os.environ.get('GYP_DEFINES', '')))
63
64
65 @memoize()
66 def distributor():
67 if 'goma' in gyp_defines():
68 return 'goma'
69 elif IsWindows():
70 if 'CHROME_HEADLESS' in os.environ:
71 return 'ib' # use (!goma and headless) as approximation of ib
72
73
74 @memoize()
75 def platform():
Isaac (away) 2012/10/24 04:54:07 Please document all of these functions.
iannucci 2012/10/24 21:40:08 But... but... self documenting code! j/k :D Done
76 if 'OS' in gyp_defines():
77 if 'android' in gyp_defines()['OS']:
78 return 'android'
79 else:
80 return gyp_defines()['OS']
81 elif IsWindows():
82 return 'win'
83 elif IsLinux():
84 return 'linux'
85 else:
86 return 'mac'
87
88
89 @memoize()
90 def builder():
Isaac (away) 2012/10/24 04:54:07 What does this function do? Some android bots use
iannucci 2012/10/24 21:40:08 Blehh... I don't want to write bot-only code here.
91 if 'GYP_GENERATORS' in os.environ:
92 # for simplicity, only support the first explicit generator
93 generator = os.environ['GYP_GENERATORS'].split(',')[0]
94 if generator == 'make-android':
95 return 'make'
96 else:
97 return generator
98 else:
99 if platform() == 'android':
100 # Good enough for now? Do any android bots use make?
101 return 'ninja'
102 elif platform() == 'ios':
103 return 'xcode'
104 elif IsWindows():
105 return 'msvs'
106 elif IsLinux():
107 return 'make'
108 elif IsMac():
109 return 'xcode'
110 else:
111 assert False, 'Don\'t know what builder we\'re using!'
112
113
114 def get_landmines(target):
115 """
116 ALL LANDMINES ARE DEFINED HERE.
117 target is 'Release' or 'Debug'
118 """
119 landmines = []
120 add = lambda item: landmines.append(item + '\n')
121
122 if (distributor() == 'goma' and platform() == 'win32' and
123 builder() == 'ninja'):
124 add('Need to clobber winja goma due to backend cwd cache fix.')
125
126 return landmines
127
128
129 def get_target_build_dir(build_tool, src_dir, target, is_iphone=False):
130 ret = None
131 if build_tool == 'xcode':
132 ret = os.path.join(src_dir, 'xcodebuild', 'content.build',
133 target + ('-iphoneos' if is_iphone else ''))
134 elif build_tool == 'make':
135 ret = os.path.join(src_dir, 'out', target)
136 elif build_tool == 'ninja':
137 ret = os.path.join(src_dir, 'out', target)
138 elif build_tool == 'msvs':
139 ret = os.path.join(src_dir, 'build', target)
140 elif build_tool == 'scons':
141 ret = os.path.join(src_dir, 'sconsbuild', target)
142 return os.path.abspath(ret)
143
144
145 def main():
146 gyp_helper.apply_chromium_gyp_env()
147 src_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
148
149 for target in ('Debug', 'Release'):
150 out_dir = get_target_build_dir(builder(), src_dir, target,
151 platform() == 'ios')
152
153 landmines_path = os.path.join(out_dir, '.landmines')
154 if not os.path.exists(out_dir):
155 os.makedirs(out_dir)
156
157 new_landmines = get_landmines(target)
158
159 if not os.path.exists(landmines_path):
160 with open(landmines_path, 'w') as f:
161 f.writelines(new_landmines)
162 else:
163 triggered = os.path.join(out_dir, '.landmines_triggered')
164 with open(landmines_path, 'r') as f:
165 old_landmines = f.readlines()
166 if old_landmines != new_landmines:
167 old_date = time.ctime(os.stat(landmines_path).st_ctime)
168 diff = difflib.unified_diff(old_landmines, new_landmines,
Isaac (away) 2012/10/24 19:23:29 Why not read these files into python, call splitli
iannucci 2012/10/24 21:40:08 Well... This is actually doing essentially that (b
169 fromfile='old_landmines', tofile='new_landmines',
170 fromfiledate=old_date, tofiledate=time.ctime(), n=0)
171
172 with open(triggered, 'w') as f:
173 f.writelines(diff)
174 elif os.path.exists(triggered):
175 # Remove false triggered landmines.
176 os.unlink(triggered)
177
178 return 0
179
180
181 if __name__ == '__main__':
182 sys.exit(main())
OLDNEW
« build/gyp_helper.py ('K') | « build/gyp_helper.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698