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

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

Issue 2138693002: [tools] Build generator script (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Review + better docu Created 4 years, 5 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 | « infra/mb/mb_config.pyl ('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 2016 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 """Script to generate V8's gn arguments based on common developer defaults
7 or builder configurations.
8
9 Goma is used by default if a goma folder is detected. The compiler proxy is
10 assumed to run.
11
12 This script can be added to the PATH and be used on other v8 checkouts than
13 the including one. It always runs for the checkout that nests the CWD.
14
15 Configurations of this script live in infra/mb/mb_config.pyl.
16
17 -------------------------------------------------------------------------------
18
19 Examples:
20
21 # Generate the x64.release config in out.gn/x64.release.
22 v8gen.py x64.release
23
24 # Generate into out.gn/foo and disable goma auto-detect.
25 v8gen.py -b x64.release foo --no-goma
26
27 # Pass additional gn arguments after -- (don't use spaces within gn args).
28 v8gen.py x64.optdebug -- v8_enable_slow_dchecks=true
29
30 # Generate gn arguments of 'V8 Linux64 - builder' from 'client.v8'. To switch
31 # off goma usage here, the args.gn file must be edited manually.
32 v8gen.py -m client.v8 -b 'V8 Linux64 - builder'
33
34 -------------------------------------------------------------------------------
35 """
36
37 import argparse
38 import os
39 import re
40 import subprocess
41 import sys
42
43 GOMA_DEFAULT = os.path.join(os.path.expanduser("~"), 'goma')
44 OUT_DIR = 'out.gn'
45
46
47 def _sanitize_nonalpha(text):
48 return re.sub(r'[^a-zA-Z0-9.]', '_', text)
49
50
51 class GenerateGnArgs(object):
52 def __init__(self, args):
53 # Split args into this script's arguments and gn args passed to the
54 # wrapped gn.
55 index = args.index('--') if '--' in args else len(args)
56 self._options = self._parse_arguments(args[:index])
57 self._gn_args = args[index + 1:]
58
59 def _parse_arguments(self, args):
60 parser = argparse.ArgumentParser(
61 description=__doc__,
62 formatter_class=argparse.RawTextHelpFormatter,
63 )
64 parser.add_argument(
65 'outdir', nargs='?',
66 help='optional gn output directory')
67 parser.add_argument(
68 '-b', '--builder',
69 help='build configuration or builder name from mb_config.pyl, e.g. '
70 'x64.release')
71 parser.add_argument(
72 '-m', '--master', default='developer_default',
73 help='config group or master from mb_config.pyl - default: '
74 'developer_default')
75 parser.add_argument(
76 '-p', '--pedantic', action='store_true',
77 help='run gn over command-line gn args to catch errors early')
78 parser.add_argument(
79 '-v', '--verbosity', action='count',
80 help='print wrapped commands (use -vv to print output of wrapped '
81 'commands)')
82
83 goma = parser.add_mutually_exclusive_group()
84 goma.add_argument(
85 '-g' , '--goma',
86 action='store_true', default=None, dest='goma',
87 help='force using goma')
88 goma.add_argument(
89 '--nogoma', '--no-goma',
90 action='store_false', default=None, dest='goma',
91 help='don\'t use goma auto detection - goma might still be used if '
92 'specified as a gn arg')
93
94 options = parser.parse_args(args)
95
96 if not options.outdir and not options.builder:
97 parser.error('please specify either an output directory or '
98 'a builder/config name (-b), e.g. x64.release')
99
100 if not options.outdir:
101 # Derive output directory from builder name.
102 options.outdir = _sanitize_nonalpha(options.builder)
103 else:
104 # Also, if this should work on windows, we might need to use \ where
105 # outdir is used as path, while using / if it's used in a gn context.
106 if options.outdir.startswith('/'):
107 parser.error(
108 'only output directories relative to %s are supported' % OUT_DIR)
109
110 if not options.builder:
111 # Derive builder from output directory.
112 options.builder = options.outdir
113
114 return options
115
116 def verbose_print_1(self, text):
117 if self._options.verbosity >= 1:
118 print '#' * 80
119 print text
120
121 def verbose_print_2(self, text):
122 if self._options.verbosity >= 2:
123 indent = ' ' * 2
124 for l in text.splitlines():
125 print indent + l
126
127 def _call_cmd(self, args):
128 self.verbose_print_1(' '.join(args))
129 try:
130 output = subprocess.check_output(
131 args=args,
132 stderr=subprocess.STDOUT,
133 )
134 self.verbose_print_2(output)
135 except subprocess.CalledProcessError as e:
136 self.verbose_print_2(e.output)
137 raise
138
139 def _find_work_dir(self, path):
140 """Find the closest v8 root to `path`."""
141 if os.path.exists(os.path.join(path, 'tools', 'dev', 'v8gen.py')):
142 # Approximate the v8 root dir by a folder where this script exists
143 # in the expected place.
144 return path
145 elif os.path.dirname(path) == path:
146 raise Exception(
147 'This appears to not be called from a recent v8 checkout')
148 else:
149 return self._find_work_dir(os.path.dirname(path))
150
151 @property
152 def _goma_dir(self):
153 return os.path.normpath(os.environ.get('GOMA_DIR') or GOMA_DEFAULT)
154
155 @property
156 def _need_goma_dir(self):
157 return self._goma_dir != GOMA_DEFAULT
158
159 @property
160 def _use_goma(self):
161 if self._options.goma is None:
162 # Auto-detect.
163 return os.path.exists(self._goma_dir) and os.path.isdir(self._goma_dir)
164 else:
165 return self._options.goma
166
167 @property
168 def _goma_args(self):
169 """Gn args for using goma."""
170 # Specify goma args if we want to use goma and if goma isn't specified
171 # via command line already. The command-line always has precedence over
172 # any other specification.
173 if (self._use_goma and
174 not any(re.match(r'use_goma\s*=.*', x) for x in self._gn_args)):
175 if self._need_goma_dir:
176 return 'use_goma=true\ngoma_dir="%s"' % self._goma_dir
177 else:
178 return 'use_goma=true'
179 else:
180 return ''
181
182 def _append_gn_args(self, type, gn_args_path, more_gn_args):
183 """Append extra gn arguments to the generated args.gn file."""
184 if not more_gn_args:
185 return False
186 self.verbose_print_1('Appending """\n%s\n""" to %s.' % (
187 more_gn_args, os.path.abspath(gn_args_path)))
188 with open(gn_args_path, 'a') as f:
189 f.write('\n# Additional %s args:\n' % type)
190 f.write(more_gn_args)
191 f.write('\n')
192 return True
193
194 def main(self):
195 # Always operate relative to the base directory for better relative-path
196 # handling. This script can be used in any v8 checkout.
197 workdir = self._find_work_dir(os.getcwd())
198 if workdir != os.getcwd():
199 self.verbose_print_1('cd ' + workdir)
200 os.chdir(workdir)
201
202 # The directories are separated with slashes in a gn context (platform
203 # independent).
204 gn_outdir = '/'.join([OUT_DIR, self._options.outdir])
205
206 # Call MB to generate the basic configuration.
207 self._call_cmd([
208 sys.executable,
209 '-u', os.path.join('tools', 'mb', 'mb.py'),
210 'gen',
211 '-f', os.path.join('infra', 'mb', 'mb_config.pyl'),
212 '-m', self._options.master,
213 '-b', self._options.builder,
214 gn_outdir,
215 ])
216
217 # Handle extra gn arguments.
218 gn_args_path = os.path.join(OUT_DIR, self._options.outdir, 'args.gn')
219
220 # Append command-line args.
221 modified = self._append_gn_args(
222 'command-line', gn_args_path, '\n'.join(self._gn_args))
223
224 # Append goma args.
225 # TODO(machenbach): We currently can't remove existing goma args from the
226 # original config. E.g. to build like a bot that uses goma, but switch
227 # goma off.
228 modified |= self._append_gn_args(
229 'goma', gn_args_path, self._goma_args)
230
231 # Regenerate ninja files to check for errors in the additional gn args.
232 if modified and self._options.pedantic:
233 self._call_cmd(['gn', 'gen', gn_outdir])
234 return 0
235
236 if __name__ == "__main__":
237 gen = GenerateGnArgs(sys.argv[1:])
238 try:
239 sys.exit(gen.main())
240 except Exception:
241 if gen._options.verbosity < 2:
242 print ('\nHint: You can raise verbosity (-vv) to see the output of '
243 'failed commands.\n')
244 raise
OLDNEW
« no previous file with comments | « infra/mb/mb_config.pyl ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698