Index: tools/mb/mb.py |
diff --git a/tools/mb/mb.py b/tools/mb/mb.py |
index b9b11963c05aaa834c10596f099aac51ec3b0531..8df9e69be4ecef20088ced8ffdee841602ba1033 100755 |
--- a/tools/mb/mb.py |
+++ b/tools/mb/mb.py |
@@ -120,6 +120,17 @@ class MetaBuildWrapper(object): |
'as a JSON object.') |
subp.set_defaults(func=self.CmdAnalyze) |
+ subp = subps.add_parser('export', |
+ help='print out the expanded configuration for' |
+ 'each builder as a JSON object') |
+ subp.add_argument('-f', '--config-file', metavar='PATH', |
+ default=self.default_config, |
+ help='path to config file ' |
+ '(default is //tools/mb/mb_config.pyl)') |
+ subp.add_argument('-g', '--goma-dir', |
+ help='path to goma directory') |
+ subp.set_defaults(func=self.CmdExport) |
+ |
subp = subps.add_parser('gen', |
help='generate a new set of build files') |
AddCommonOptions(subp) |
@@ -249,6 +260,33 @@ class MetaBuildWrapper(object): |
else: |
return self.RunGYPAnalyze(vals) |
+ def CmdExport(self): |
+ self.ReadConfigFile() |
+ obj = {} |
+ for master, builders in self.masters.items(): |
+ obj[master] = {} |
+ for builder in builders: |
+ config = self.masters[master][builder] |
+ if not config: |
+ continue |
+ |
+ if isinstance(config, list): |
+ args = [self.FlattenConfig(c)['gn_args'] for c in config] |
+ elif config.startswith('//'): |
+ args = config |
+ else: |
+ args = self.FlattenConfig(config)['gn_args'] |
+ if 'error' in args: |
+ continue |
+ |
+ obj[master][builder] = args |
+ |
+ # Dump object and trim trailing whitespace. |
+ s = '\n'.join(l.rstrip() for l in |
+ json.dumps(obj, sort_keys=True, indent=2).splitlines()) |
+ self.Print(s) |
+ return 0 |
+ |
def CmdGen(self): |
vals = self.Lookup() |
self.ClobberIfNeeded(vals) |
@@ -526,7 +564,7 @@ class MetaBuildWrapper(object): |
def GetConfig(self): |
build_dir = self.args.path[0] |
- vals = {} |
+ vals = self.DefaultVals() |
if self.args.builder or self.args.master or self.args.config: |
vals = self.Lookup() |
if vals['type'] == 'gn': |
@@ -550,14 +588,12 @@ class MetaBuildWrapper(object): |
mb_type = self.ReadFile(mb_type_path).strip() |
if mb_type == 'gn': |
- vals = self.GNValsFromDir(build_dir) |
- else: |
- vals = {} |
+ vals['gn_args'] = self.GNArgsFromDir(build_dir) |
vals['type'] = mb_type |
return vals |
- def GNValsFromDir(self, build_dir): |
+ def GNArgsFromDir(self, build_dir): |
args_contents = "" |
gn_args_path = self.PathJoin(self.ToAbsPath(build_dir), 'args.gn') |
if self.Exists(gn_args_path): |
@@ -569,27 +605,18 @@ class MetaBuildWrapper(object): |
val = ' '.join(fields[2:]) |
gn_args.append('%s=%s' % (name, val)) |
- return { |
- 'gn_args': ' '.join(gn_args), |
- 'type': 'gn', |
- } |
+ return ' '.join(gn_args) |
def Lookup(self): |
- vals = self.ReadBotConfig() |
+ vals = self.ReadIOSBotConfig() |
if not vals: |
self.ReadConfigFile() |
config = self.ConfigFromArgs() |
if config.startswith('//'): |
if not self.Exists(self.ToAbsPath(config)): |
raise MBErr('args file "%s" not found' % config) |
- vals = { |
- 'args_file': config, |
- 'cros_passthrough': False, |
- 'gn_args': '', |
- 'gyp_crosscompile': False, |
- 'gyp_defines': '', |
- 'type': 'gn', |
- } |
+ vals = self.DefaultVals() |
+ vals['args_file'] = config |
else: |
if not config in self.configs: |
raise MBErr('Config "%s" not found in %s' % |
@@ -598,13 +625,14 @@ class MetaBuildWrapper(object): |
# Do some basic sanity checking on the config so that we |
# don't have to do this in every caller. |
- assert 'type' in vals, 'No meta-build type specified in the config' |
+ if 'type' not in vals: |
+ vals['type'] = 'gn' |
assert vals['type'] in ('gn', 'gyp'), ( |
'Unknown meta-build type "%s"' % vals['gn_args']) |
return vals |
- def ReadBotConfig(self): |
+ def ReadIOSBotConfig(self): |
if not self.args.master or not self.args.builder: |
return {} |
path = self.PathJoin(self.chromium_src_dir, 'ios', 'build', 'bots', |
@@ -620,14 +648,11 @@ class MetaBuildWrapper(object): |
gyp_defines = ' '.join(gyp_vals) |
gn_args = ' '.join(contents.get('gn_args', [])) |
- return { |
- 'args_file': '', |
- 'cros_passthrough': False, |
- 'gn_args': gn_args, |
- 'gyp_crosscompile': False, |
- 'gyp_defines': gyp_defines, |
- 'type': contents.get('mb_type', ''), |
- } |
+ vals = self.DefaultVals() |
+ vals['gn_args'] = gn_args |
+ vals['gyp_defines'] = gyp_defines |
+ vals['type'] = contents.get('mb_type', 'gn') |
+ return vals |
def ReadConfigFile(self): |
if not self.Exists(self.args.config_file): |
@@ -685,19 +710,22 @@ class MetaBuildWrapper(object): |
def FlattenConfig(self, config): |
mixins = self.configs[config] |
- vals = { |
+ vals = self.DefaultVals() |
+ |
+ visited = [] |
+ self.FlattenMixins(mixins, vals, visited) |
+ return vals |
+ |
+ def DefaultVals(self): |
+ return { |
'args_file': '', |
'cros_passthrough': False, |
- 'gn_args': [], |
+ 'gn_args': '', |
'gyp_defines': '', |
'gyp_crosscompile': False, |
- 'type': None, |
+ 'type': 'gn', |
} |
- visited = [] |
- self.FlattenMixins(mixins, vals, visited) |
- return vals |
- |
def FlattenMixins(self, mixins, vals, visited): |
for m in mixins: |
if m not in self.mixins: |