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

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: ich habe die nit fixiert Created 8 years, 1 month 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 """Parses and returns GYP_DEFINES env var as a dictionary."""
62 return dict(arg.split('=', 1)
63 for arg in shlex.split(os.environ.get('GYP_DEFINES', '')))
64
65
66 @memoize()
67 def distributor():
68 """
69 Returns a string which is the distributed build engine in use (if any).
70 Possible values: 'goma', 'ib', ''
71 """
72 if 'goma' in gyp_defines():
73 return 'goma'
74 elif IsWindows():
75 if 'CHROME_HEADLESS' in os.environ:
76 return 'ib' # use (win and !goma and headless) as approximation of ib
77
78
79 @memoize()
80 def platform():
81 """
82 Returns a string representing the platform this build is targetted for.
83 Possible values: 'win', 'mac', 'linux', 'ios', 'android'
84 """
85 if 'OS' in gyp_defines():
86 if 'android' in gyp_defines()['OS']:
87 return 'android'
88 else:
89 return gyp_defines()['OS']
90 elif IsWindows():
91 return 'win'
92 elif IsLinux():
93 return 'linux'
94 else:
95 return 'mac'
96
97
98 @memoize()
99 def builder():
100 """
101 Returns a string representing the build engine (not compiler) to use.
102 Possible values: 'make', 'ninja', 'xcode', 'msvs', 'scons'
103 """
104 if 'GYP_GENERATORS' in os.environ:
105 # for simplicity, only support the first explicit generator
106 generator = os.environ['GYP_GENERATORS'].split(',')[0]
107 if generator.endswith('-android'):
108 return generator.split('-')[0]
109 else:
110 return generator
111 else:
112 if platform() == 'android':
113 # Good enough for now? Do any android bots use make?
114 return 'ninja'
115 elif platform() == 'ios':
116 return 'xcode'
117 elif IsWindows():
118 return 'msvs'
119 elif IsLinux():
120 return 'make'
121 elif IsMac():
122 return 'xcode'
123 else:
124 assert False, 'Don\'t know what builder we\'re using!'
125
126
127 def get_landmines(target):
128 """
129 ALL LANDMINES ARE DEFINED HERE.
130 target is 'Release' or 'Debug'
131 """
132 landmines = []
133 add = lambda item: landmines.append(item + '\n')
134
135 if (distributor() == 'goma' and platform() == 'win32' and
136 builder() == 'ninja'):
137 add('Need to clobber winja goma due to backend cwd cache fix.')
138
139 return landmines
140
141
142 def get_target_build_dir(build_tool, src_dir, target, is_iphone=False):
143 """
144 Get absolute path to the output directory dependant on build and target.
M-A Ruel 2012/10/29 15:10:43 Returns output directory absolute path dependent o
iannucci 2012/10/29 23:56:39 Done.
145 Examples:
146 r'c:\b\build\slave\win\build\src\out\Release'
147 '/mnt/data/b/build/slave/linux/build/src/out/Debug'
148 '/b/build/slave/ios_rel_device/build/src/xcodebuild/Release-iphoneos'
149 """
150 ret = None
151 if build_tool == 'xcode':
M-A Ruel 2012/10/29 15:10:43 My feeling: you should destroy them all. Much simp
iannucci 2012/10/29 23:56:39 No support for anything else? I still need xcode i
M-A Ruel 2012/10/30 00:53:09 Sorry I wasn't clear, I meant: delete all of these
152 ret = os.path.join(src_dir, 'xcodebuild',
153 target + ('-iphoneos' if is_iphone else ''))
154 elif build_tool == 'make':
155 ret = os.path.join(src_dir, 'out', target)
156 elif build_tool == 'ninja':
157 ret = os.path.join(src_dir, 'out', target)
158 elif build_tool == 'msvs':
159 ret = os.path.join(src_dir, 'build', target)
160 elif build_tool == 'scons':
161 ret = os.path.join(src_dir, 'sconsbuild', target)
M-A Ruel 2012/10/29 15:10:43 else: raise NotImplementError()
iannucci 2012/10/29 23:56:39 Done.
162 return os.path.abspath(ret)
163
164
165 def main():
M-A Ruel 2012/10/29 15:10:43 if len(sys.argv) > 1: print('Unknown argument %s
iannucci 2012/10/29 23:56:39 A lot of words for: assert len(sys.argv) == 1,
166 gyp_helper.apply_chromium_gyp_env()
167 src_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
M-A Ruel 2012/10/29 15:10:43 Use a global variable.
iannucci 2012/10/29 23:56:39 Done.
168
169 for target in ('Debug', 'Release'):
170 out_dir = get_target_build_dir(builder(), src_dir, target,
171 platform() == 'ios')
172
173 landmines_path = os.path.join(out_dir, '.landmines')
174 if not os.path.exists(out_dir):
175 os.makedirs(out_dir)
176
177 new_landmines = get_landmines(target)
178
179 if not os.path.exists(landmines_path):
180 with open(landmines_path, 'w') as f:
181 f.writelines(new_landmines)
182 else:
183 triggered = os.path.join(out_dir, '.landmines_triggered')
184 with open(landmines_path, 'r') as f:
185 old_landmines = f.readlines()
186 if old_landmines != new_landmines:
187 old_date = time.ctime(os.stat(landmines_path).st_ctime)
188 diff = difflib.unified_diff(old_landmines, new_landmines,
189 fromfile='old_landmines', tofile='new_landmines',
190 fromfiledate=old_date, tofiledate=time.ctime(), n=0)
191
192 with open(triggered, 'w') as f:
193 f.writelines(diff)
194 elif os.path.exists(triggered):
195 # Remove false triggered landmines.
196 os.remove(triggered)
197
198 return 0
199
200
201 if __name__ == '__main__':
202 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