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

Side by Side Diff: tools/dev/gm.py

Issue 2713663002: [tools] Introduce gm.py (Closed)
Patch Set: refactored Created 3 years, 10 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
« no previous file with comments | « no previous file | 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 2017 the V8 project 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 Convenience wrapper for compiling V8 with gn/ninja and running tests.
7 Sets up build output directories if they don't exist.
8 Produces simulator builds for non-Intel target architectures.
9 Uses Goma by default if it is detected (at output directory setup time).
10 Expects to be run from the root of a V8 checkout.
11
12 Usage:
13 gm.py [<arch>].[<mode>].[<target>] [testname...]
14
15 All arguments are optional. Most combinations should work, e.g.:
16 gm.py ia32.debug x64.release d8
17 gm.py x64 mjsunit/foo cctest/test-bar/*
18 """
19 # See HELP below for additional documentation.
20
21 import os
22 import subprocess
23 import sys
24
25 BUILD_OPTS_DEFAULT = ""
26 BUILD_OPTS_GOMA = "-j1000 -l50"
27 BUILD_TARGETS_TEST = ["d8", "cctest", "unittests"]
28 BUILD_TARGETS_ALL = ["all"]
29
30 # All arches that this script understands.
31 ARCHES = ["ia32", "x64", "arm", "arm64", "mipsel", "mips64el", "ppc", "ppc64",
32 "s390", "s390x", "x87"]
33 # Arches that get built/run when you don't specify any.
34 DEFAULT_ARCHES = ["ia32", "x64", "arm", "arm64"]
35 # Modes that this script understands.
36 MODES = ["release", "debug", "optdebug"]
37 # Modes that get built/run when you don't specify any.
38 DEFAULT_MODES = ["release", "debug"]
39 # Build targets that can be manually specified.
40 TARGETS = ["d8", "cctest", "unittests", "v8_fuzzers"]
41 # Build targets that get built when you don't specify any (and specified tests
42 # don't imply any other targets).
43 DEFAULT_TARGETS = ["d8"]
44 # Tests that run-tests.py would run by default that can be run with
45 # BUILD_TARGETS_TESTS.
46 DEFAULT_TESTS = ["cctest", "debugger", "intl", "message", "mjsunit",
47 "preparser", "unittests"]
48 # These can be suffixed to any <arch>.<mode> combo, or used standalone,
49 # or used as global modifiers (affecting all <arch>.<mode> combos).
50 ACTIONS = {
51 "all": {"targets": BUILD_TARGETS_ALL, "tests": []},
52 "tests": {"targets": BUILD_TARGETS_TEST, "tests": []},
53 "check": {"targets": BUILD_TARGETS_TEST, "tests": DEFAULT_TESTS},
54 "checkall": {"targets": BUILD_TARGETS_ALL, "tests": ["ALL"]},
55 }
56
57 HELP = """<arch> can be any of: %(arches)s
58 <mode> can be any of: %(modes)s
59 <target> can be any of:
60 - cctest, d8, unittests, v8_fuzzers (build respective binary)
61 - all (build all binaries)
62 - tests (build test binaries)
63 - check (build test binaries, run most tests)
64 - checkall (build all binaries, run more tests)
65 """ % {"arches": " ".join(ARCHES),
66 "modes": " ".join(MODES)}
67
68 TESTSUITES_TARGETS = {"benchmarks": "d8",
69 "cctest": "cctest",
70 "debugger": "d8",
71 "fuzzer": "v8_fuzzers",
72 "intl": "d8",
73 "message": "d8",
74 "mjsunit": "d8",
75 "mozilla": "d8",
76 "preparser": "d8",
77 "test262": "d8",
78 "unittests": "unittests",
79 "webkit": "d8"}
80
81 OUTDIR = "out"
82
83 IS_GOMA_MACHINE = (os.path.exists(os.path.expanduser("~/goma")) or
84 os.environ.get('GOMADIR'))
85
86 USE_GOMA = "true" if IS_GOMA_MACHINE else "false"
87 BUILD_OPTS = BUILD_OPTS_GOMA if IS_GOMA_MACHINE else BUILD_OPTS_DEFAULT
88
89 RELEASE_ARGS_TEMPLATE = """\
90 is_component_build = false
91 is_debug = false
92 %s
93 use_goma = {GOMA}
94 v8_enable_backtrace = true
95 v8_enable_disassembler = true
96 v8_enable_object_print = true
97 v8_enable_verify_heap = true
98 """.replace("{GOMA}", USE_GOMA)
99
100 DEBUG_ARGS_TEMPLATE = """\
101 gdb_index = true
102 is_component_build = true
103 is_debug = true
104 symbol_level = 2
105 %s
106 use_goma = {GOMA}
107 v8_enable_backtrace = true
108 v8_enable_slow_dchecks = true
109 v8_optimized_debug = false
110 """.replace("{GOMA}", USE_GOMA)
111
112 OPTDEBUG_ARGS_TEMPLATE = """\
113 gdb_index = false
114 is_component_build = true
115 is_debug = true
116 symbol_level = 1
117 %s
118 use_goma = {GOMA}
119 v8_enable_backtrace = true
120 v8_enable_verify_heap = true
121 v8_optimized_debug = true
122 """.replace("{GOMA}", USE_GOMA)
123
124 ARGS_TEMPLATES = {
125 "release": RELEASE_ARGS_TEMPLATE,
126 "debug": DEBUG_ARGS_TEMPLATE,
127 "optdebug": OPTDEBUG_ARGS_TEMPLATE
128 }
129
130 def PrintHelpAndExit():
131 print(__doc__)
132 print(HELP)
133 sys.exit(0)
134
135 def _Call(cmd, silent=False):
136 if not silent: print("# %s" % cmd)
137 return subprocess.call(cmd, shell=True)
138
139 def _Write(filename, content):
140 print("# echo > %s << EOF\n%sEOF" % (filename, content))
141 with open(filename, "w") as f:
142 f.write(content)
143
144 def GetPath(arch, mode):
145 subdir = "%s.%s" % (arch, mode)
146 return os.path.join(OUTDIR, subdir)
147
148 class Config(object):
149 def __init__(self, arch, mode, targets, tests=[]):
150 self.arch = arch
151 self.mode = mode
152 self.targets = set(targets)
153 self.tests = set(tests)
154
155 def Extend(self, targets, tests=[]):
156 self.targets.update(targets)
157 self.tests.update(tests)
158
159 def GetTargetCpu(self):
160 cpu = "x86"
161 if self.arch.endswith("64") or self.arch == "s390x":
162 cpu = "x64"
163 return "target_cpu = \"%s\"" % cpu
164
165 def GetV8TargetCpu(self):
166 if self.arch in ("arm", "arm64", "mipsel", "mips64el", "ppc", "ppc64",
167 "s390", "s390x"):
168 return "\nv8_target_cpu = \"%s\"" % self.arch
169 return ""
170
171 def GetGnArgs(self):
172 template = ARGS_TEMPLATES[self.mode]
173 arch_specific = self.GetTargetCpu() + self.GetV8TargetCpu()
174 return template % arch_specific
175
176 def Build(self):
177 path = GetPath(self.arch, self.mode)
178 args_gn = os.path.join(path, "args.gn")
179 if not os.path.exists(path):
180 print("# mkdir -p %s" % path)
181 os.makedirs(path)
182 if not os.path.exists(args_gn):
183 _Write(args_gn, self.GetGnArgs())
184 code = _Call("gn gen %s" % path)
185 if code != 0: return code
186 targets = " ".join(self.targets)
187 return _Call("ninja -C %s %s %s" % (path, BUILD_OPTS, targets))
188
189 def RunTests(self):
190 if not self.tests: return 0
191 if "ALL" in self.tests:
192 tests = ""
193 else:
194 tests = " ".join(self.tests)
195 return _Call("tools/run-tests.py --arch=%s --mode=%s %s" %
196 (self.arch, self.mode, tests))
197
198 def GetTestBinary(argstring):
199 for suite in TESTSUITES_TARGETS:
200 if argstring.startswith(suite): return TESTSUITES_TARGETS[suite]
201 return None
202
203 class ArgumentParser(object):
204 def __init__(self):
205 self.global_targets = set()
206 self.global_tests = set()
207 self.global_actions = set()
208 self.configs = {}
209
210 def PopulateConfigs(self, arches, modes, targets, tests):
211 for a in arches:
212 for m in modes:
213 path = GetPath(a, m)
214 if path not in self.configs:
215 self.configs[path] = Config(a, m, targets, tests)
216 else:
217 self.configs[path].Extend(targets, tests)
218
219 def ProcessGlobalActions(self):
220 have_configs = len(self.configs) > 0
221 for action in self.global_actions:
222 impact = ACTIONS[action]
223 if (have_configs):
224 for c in self.configs:
225 self.configs[c].Extend(**impact)
226 else:
227 self.PopulateConfigs(DEFAULT_ARCHES, DEFAULT_MODES, **impact)
228
229 def ParseArg(self, argstring):
230 if argstring in ("-h", "--help", "help"):
231 PrintHelpAndExit()
232 arches = []
233 modes = []
234 targets = []
235 actions = []
236 tests = []
237 words = argstring.split('.')
238 if len(words) == 1:
239 word = words[0]
240 if word in ACTIONS:
241 self.global_actions.add(word)
242 return
243 if word in TARGETS:
244 self.global_targets.add(word)
245 return
246 maybe_target = GetTestBinary(word)
247 if maybe_target is not None:
248 self.global_tests.add(word)
249 self.global_targets.add(maybe_target)
250 return
251 for word in words:
252 if word in ARCHES:
253 arches.append(word)
254 elif word in MODES:
255 modes.append(word)
256 elif word in TARGETS:
257 targets.append(word)
258 elif word in ACTIONS:
259 actions.append(word)
260 else:
261 print("Didn't understand: %s" % word)
262 sys.exit(1)
263 # Process actions.
264 for action in actions:
265 impact = ACTIONS[action]
266 targets += impact["targets"]
267 tests += impact["tests"]
268 # Fill in defaults for things that weren't specified.
269 arches = arches or DEFAULT_ARCHES
270 modes = modes or DEFAULT_MODES
271 targets = targets or DEFAULT_TARGETS
272 # Produce configs.
273 self.PopulateConfigs(arches, modes, targets, tests)
274
275 def ParseArguments(self, argv):
276 if len(argv) == 0:
277 PrintHelpAndExit()
278 for argstring in argv:
279 self.ParseArg(argstring)
280 self.ProcessGlobalActions()
281 for c in self.configs:
282 self.configs[c].Extend(self.global_targets, self.global_tests)
283 return self.configs
284
285 def Main(argv):
286 parser = ArgumentParser()
287 configs = parser.ParseArguments(argv[1:])
288 return_code = 0
289 for c in configs:
290 return_code += configs[c].Build()
291 for c in configs:
292 return_code += configs[c].RunTests()
293 if return_code == 0:
294 _Call("notify-send 'Done!' 'V8 compilation finished successfully.'",
295 silent=True)
296 else:
297 _Call("notify-send 'Error!' 'V8 compilation finished with errors.'",
298 silent=True)
299 return return_code
300
301 if __name__ == "__main__":
302 sys.exit(Main(sys.argv))
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698