Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright 2015 The Chromium Authors. All rights reserved. | 2 # Copyright 2015 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """MB - the Meta-Build wrapper around GYP and GN | 6 """MB - the Meta-Build wrapper around GYP and GN |
| 7 | 7 |
| 8 MB is a wrapper script for GYP and GN that can be used to generate build files | 8 MB is a wrapper script for GYP and GN that can be used to generate build files |
| 9 for sets of canned configurations and analyze them. | 9 for sets of canned configurations and analyze them. |
| 10 """ | 10 """ |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 140 if vals['type'] == 'gyp': | 140 if vals['type'] == 'gyp': |
| 141 return self.RunGYPGen(vals) | 141 return self.RunGYPGen(vals) |
| 142 | 142 |
| 143 raise MBErr('Unknown meta-build type "%s"' % vals['type']) | 143 raise MBErr('Unknown meta-build type "%s"' % vals['type']) |
| 144 | 144 |
| 145 def CmdLookup(self): | 145 def CmdLookup(self): |
| 146 vals = self.GetConfig() | 146 vals = self.GetConfig() |
| 147 if vals['type'] == 'gn': | 147 if vals['type'] == 'gn': |
| 148 cmd = self.GNCmd('gen', '<path>', vals['gn_args']) | 148 cmd = self.GNCmd('gen', '<path>', vals['gn_args']) |
| 149 elif vals['type'] == 'gyp': | 149 elif vals['type'] == 'gyp': |
| 150 if vals['gyp_crosscompile']: | |
| 151 self.Print('GYP_CROSSCOMPILE=1') | |
| 150 cmd = self.GYPCmd('<path>', vals['gyp_defines'], vals['gyp_config']) | 152 cmd = self.GYPCmd('<path>', vals['gyp_defines'], vals['gyp_config']) |
| 151 else: | 153 else: |
| 152 raise MBErr('Unknown meta-build type "%s"' % vals['type']) | 154 raise MBErr('Unknown meta-build type "%s"' % vals['type']) |
| 153 | 155 |
| 154 self.PrintCmd(cmd) | 156 self.PrintCmd(cmd) |
| 155 return 0 | 157 return 0 |
| 156 | 158 |
| 157 def CmdHelp(self): | 159 def CmdHelp(self): |
| 158 if self.args.subcommand: | 160 if self.args.subcommand: |
| 159 self.ParseArgs([self.args.subcommand, '--help']) | 161 self.ParseArgs([self.args.subcommand, '--help']) |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 282 | 284 |
| 283 return self.masters[self.args.master][self.args.builder] | 285 return self.masters[self.args.master][self.args.builder] |
| 284 | 286 |
| 285 def FlattenConfig(self, config): | 287 def FlattenConfig(self, config): |
| 286 mixins = self.configs[config] | 288 mixins = self.configs[config] |
| 287 vals = { | 289 vals = { |
| 288 'type': None, | 290 'type': None, |
| 289 'gn_args': [], | 291 'gn_args': [], |
| 290 'gyp_config': [], | 292 'gyp_config': [], |
| 291 'gyp_defines': [], | 293 'gyp_defines': [], |
| 294 'gyp_crosscompile': False, | |
| 292 } | 295 } |
| 293 | 296 |
| 294 visited = [] | 297 visited = [] |
| 295 self.FlattenMixins(mixins, vals, visited) | 298 self.FlattenMixins(mixins, vals, visited) |
| 296 return vals | 299 return vals |
| 297 | 300 |
| 298 def FlattenMixins(self, mixins, vals, visited): | 301 def FlattenMixins(self, mixins, vals, visited): |
| 299 for m in mixins: | 302 for m in mixins: |
| 300 if m not in self.mixins: | 303 if m not in self.mixins: |
| 301 raise MBErr('Unknown mixin "%s"' % m) | 304 raise MBErr('Unknown mixin "%s"' % m) |
| 302 | 305 |
| 303 # TODO: check for cycles in mixins. | 306 # TODO: check for cycles in mixins. |
| 304 | 307 |
| 305 visited.append(m) | 308 visited.append(m) |
| 306 | 309 |
| 307 mixin_vals = self.mixins[m] | 310 mixin_vals = self.mixins[m] |
| 308 if 'type' in mixin_vals: | 311 if 'type' in mixin_vals: |
| 309 vals['type'] = mixin_vals['type'] | 312 vals['type'] = mixin_vals['type'] |
| 310 if 'gn_args' in mixin_vals: | 313 if 'gn_args' in mixin_vals: |
| 311 if vals['gn_args']: | 314 if vals['gn_args']: |
| 312 vals['gn_args'] += ' ' + mixin_vals['gn_args'] | 315 vals['gn_args'] += ' ' + mixin_vals['gn_args'] |
| 313 else: | 316 else: |
| 314 vals['gn_args'] = mixin_vals['gn_args'] | 317 vals['gn_args'] = mixin_vals['gn_args'] |
| 315 if 'gyp_config' in mixin_vals: | 318 if 'gyp_config' in mixin_vals: |
| 316 vals['gyp_config'] = mixin_vals['gyp_config'] | 319 vals['gyp_config'] = mixin_vals['gyp_config'] |
| 320 if 'gyp_crosscompile' in mixin_vals: | |
| 321 vals['gyp_crosscompile'] = mixin_vals['gyp_crosscompile'] | |
| 317 if 'gyp_defines' in mixin_vals: | 322 if 'gyp_defines' in mixin_vals: |
| 318 if vals['gyp_defines']: | 323 if vals['gyp_defines']: |
| 319 vals['gyp_defines'] += ' ' + mixin_vals['gyp_defines'] | 324 vals['gyp_defines'] += ' ' + mixin_vals['gyp_defines'] |
| 320 else: | 325 else: |
| 321 vals['gyp_defines'] = mixin_vals['gyp_defines'] | 326 vals['gyp_defines'] = mixin_vals['gyp_defines'] |
| 322 if 'mixins' in mixin_vals: | 327 if 'mixins' in mixin_vals: |
| 323 self.FlattenMixins(mixin_vals['mixins'], vals, visited) | 328 self.FlattenMixins(mixin_vals['mixins'], vals, visited) |
| 324 return vals | 329 return vals |
| 325 | 330 |
| 326 def RunGNGen(self, vals): | 331 def RunGNGen(self, vals): |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 419 | 424 |
| 420 def RunGYPGen(self, vals): | 425 def RunGYPGen(self, vals): |
| 421 path = self.args.path[0] | 426 path = self.args.path[0] |
| 422 | 427 |
| 423 output_dir, gyp_config = self.ParseGYPConfigPath(path) | 428 output_dir, gyp_config = self.ParseGYPConfigPath(path) |
| 424 if gyp_config != vals['gyp_config']: | 429 if gyp_config != vals['gyp_config']: |
| 425 raise MBErr('The last component of the path (%s) must match the ' | 430 raise MBErr('The last component of the path (%s) must match the ' |
| 426 'GYP configuration specified in the config (%s), and ' | 431 'GYP configuration specified in the config (%s), and ' |
| 427 'it does not.' % (gyp_config, vals['gyp_config'])) | 432 'it does not.' % (gyp_config, vals['gyp_config'])) |
| 428 cmd = self.GYPCmd(output_dir, vals['gyp_defines'], config=gyp_config) | 433 cmd = self.GYPCmd(output_dir, vals['gyp_defines'], config=gyp_config) |
| 429 ret, _, _ = self.Run(cmd) | 434 env = os.environ.copy() |
| 435 if vals['gyp_crosscompile']: | |
| 436 if self.args.verbose: | |
| 437 self.Print('Setting GYP_CROSSCOMPILE=1 in the environment') | |
| 438 env['GYP_CROSSCOMPILE'] = '1' | |
|
Nico
2015/08/14 00:14:30
Hm, this copy-env-and-set pattern has caused me tr
Dirk Pranke
2015/08/14 00:19:17
I'm not sure why that would make a difference, but
| |
| 439 ret, _, _ = self.Run(cmd, env=env) | |
| 430 return ret | 440 return ret |
| 431 | 441 |
| 432 def RunGYPAnalyze(self, vals): | 442 def RunGYPAnalyze(self, vals): |
| 433 output_dir, gyp_config = self.ParseGYPConfigPath(self.args.path[0]) | 443 output_dir, gyp_config = self.ParseGYPConfigPath(self.args.path[0]) |
| 434 if gyp_config != vals['gyp_config']: | 444 if gyp_config != vals['gyp_config']: |
| 435 raise MBErr('The last component of the path (%s) must match the ' | 445 raise MBErr('The last component of the path (%s) must match the ' |
| 436 'GYP configuration specified in the config (%s), and ' | 446 'GYP configuration specified in the config (%s), and ' |
| 437 'it does not.' % (gyp_config, vals['gyp_config'])) | 447 'it does not.' % (gyp_config, vals['gyp_config'])) |
| 438 if self.args.verbose: | 448 if self.args.verbose: |
| 439 inp = self.ReadInputJSON(['files', 'targets']) | 449 inp = self.ReadInputJSON(['files', 'targets']) |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 745 cmd = ['python'] + cmd[1:] | 755 cmd = ['python'] + cmd[1:] |
| 746 self.Print(*[pipes.quote(c) for c in cmd]) | 756 self.Print(*[pipes.quote(c) for c in cmd]) |
| 747 | 757 |
| 748 def PrintJSON(self, obj): | 758 def PrintJSON(self, obj): |
| 749 self.Print(json.dumps(obj, indent=2, sort_keys=True)) | 759 self.Print(json.dumps(obj, indent=2, sort_keys=True)) |
| 750 | 760 |
| 751 def Print(self, *args, **kwargs): | 761 def Print(self, *args, **kwargs): |
| 752 # This function largely exists so it can be overridden for testing. | 762 # This function largely exists so it can be overridden for testing. |
| 753 print(*args, **kwargs) | 763 print(*args, **kwargs) |
| 754 | 764 |
| 755 def Run(self, cmd): | 765 def Run(self, cmd, env=None): |
| 756 # This function largely exists so it can be overridden for testing. | 766 # This function largely exists so it can be overridden for testing. |
| 757 if self.args.dryrun or self.args.verbose: | 767 if self.args.dryrun or self.args.verbose: |
| 758 self.PrintCmd(cmd) | 768 self.PrintCmd(cmd) |
| 759 if self.args.dryrun: | 769 if self.args.dryrun: |
| 760 return 0, '', '' | 770 return 0, '', '' |
| 761 ret, out, err = self.Call(cmd) | 771 ret, out, err = self.Call(cmd, env=env) |
| 762 if self.args.verbose: | 772 if self.args.verbose: |
| 763 if out: | 773 if out: |
| 764 self.Print(out, end='') | 774 self.Print(out, end='') |
| 765 if err: | 775 if err: |
| 766 self.Print(err, end='', file=sys.stderr) | 776 self.Print(err, end='', file=sys.stderr) |
| 767 return ret, out, err | 777 return ret, out, err |
| 768 | 778 |
| 769 def Call(self, cmd): | 779 def Call(self, cmd, env=None): |
| 770 p = subprocess.Popen(cmd, shell=False, cwd=self.chromium_src_dir, | 780 p = subprocess.Popen(cmd, shell=False, cwd=self.chromium_src_dir, |
| 771 stdout=subprocess.PIPE, stderr=subprocess.PIPE) | 781 stdout=subprocess.PIPE, stderr=subprocess.PIPE, |
| 782 env=env) | |
| 772 out, err = p.communicate() | 783 out, err = p.communicate() |
| 773 return p.returncode, out, err | 784 return p.returncode, out, err |
| 774 | 785 |
| 775 def ExpandUser(self, path): | 786 def ExpandUser(self, path): |
| 776 # This function largely exists so it can be overridden for testing. | 787 # This function largely exists so it can be overridden for testing. |
| 777 return os.path.expanduser(path) | 788 return os.path.expanduser(path) |
| 778 | 789 |
| 779 def Exists(self, path): | 790 def Exists(self, path): |
| 780 # This function largely exists so it can be overridden for testing. | 791 # This function largely exists so it can be overridden for testing. |
| 781 return os.path.exists(path) | 792 return os.path.exists(path) |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 814 | 825 |
| 815 if __name__ == '__main__': | 826 if __name__ == '__main__': |
| 816 try: | 827 try: |
| 817 sys.exit(main(sys.argv[1:])) | 828 sys.exit(main(sys.argv[1:])) |
| 818 except MBErr as e: | 829 except MBErr as e: |
| 819 print(e) | 830 print(e) |
| 820 sys.exit(1) | 831 sys.exit(1) |
| 821 except KeyboardInterrupt: | 832 except KeyboardInterrupt: |
| 822 print("interrupted, exiting", stream=sys.stderr) | 833 print("interrupted, exiting", stream=sys.stderr) |
| 823 sys.exit(130) | 834 sys.exit(130) |
| OLD | NEW |