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 = None |
| 435 if vals['gyp_crosscompile']: |
| 436 if self.args.verbose: |
| 437 self.Print('Setting GYP_CROSSCOMPILE=1 in the environment') |
| 438 env = os.environ.copy() |
| 439 env['GYP_CROSSCOMPILE'] = '1' |
| 440 ret, _, _ = self.Run(cmd, env=env) |
430 return ret | 441 return ret |
431 | 442 |
432 def RunGYPAnalyze(self, vals): | 443 def RunGYPAnalyze(self, vals): |
433 output_dir, gyp_config = self.ParseGYPConfigPath(self.args.path[0]) | 444 output_dir, gyp_config = self.ParseGYPConfigPath(self.args.path[0]) |
434 if gyp_config != vals['gyp_config']: | 445 if gyp_config != vals['gyp_config']: |
435 raise MBErr('The last component of the path (%s) must match the ' | 446 raise MBErr('The last component of the path (%s) must match the ' |
436 'GYP configuration specified in the config (%s), and ' | 447 'GYP configuration specified in the config (%s), and ' |
437 'it does not.' % (gyp_config, vals['gyp_config'])) | 448 'it does not.' % (gyp_config, vals['gyp_config'])) |
438 if self.args.verbose: | 449 if self.args.verbose: |
439 inp = self.ReadInputJSON(['files', 'targets']) | 450 inp = self.ReadInputJSON(['files', 'targets']) |
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
745 cmd = ['python'] + cmd[1:] | 756 cmd = ['python'] + cmd[1:] |
746 self.Print(*[pipes.quote(c) for c in cmd]) | 757 self.Print(*[pipes.quote(c) for c in cmd]) |
747 | 758 |
748 def PrintJSON(self, obj): | 759 def PrintJSON(self, obj): |
749 self.Print(json.dumps(obj, indent=2, sort_keys=True)) | 760 self.Print(json.dumps(obj, indent=2, sort_keys=True)) |
750 | 761 |
751 def Print(self, *args, **kwargs): | 762 def Print(self, *args, **kwargs): |
752 # This function largely exists so it can be overridden for testing. | 763 # This function largely exists so it can be overridden for testing. |
753 print(*args, **kwargs) | 764 print(*args, **kwargs) |
754 | 765 |
755 def Run(self, cmd): | 766 def Run(self, cmd, env=None): |
756 # This function largely exists so it can be overridden for testing. | 767 # This function largely exists so it can be overridden for testing. |
757 if self.args.dryrun or self.args.verbose: | 768 if self.args.dryrun or self.args.verbose: |
758 self.PrintCmd(cmd) | 769 self.PrintCmd(cmd) |
759 if self.args.dryrun: | 770 if self.args.dryrun: |
760 return 0, '', '' | 771 return 0, '', '' |
761 ret, out, err = self.Call(cmd) | 772 ret, out, err = self.Call(cmd, env=env) |
762 if self.args.verbose: | 773 if self.args.verbose: |
763 if out: | 774 if out: |
764 self.Print(out, end='') | 775 self.Print(out, end='') |
765 if err: | 776 if err: |
766 self.Print(err, end='', file=sys.stderr) | 777 self.Print(err, end='', file=sys.stderr) |
767 return ret, out, err | 778 return ret, out, err |
768 | 779 |
769 def Call(self, cmd): | 780 def Call(self, cmd, env=None): |
770 p = subprocess.Popen(cmd, shell=False, cwd=self.chromium_src_dir, | 781 p = subprocess.Popen(cmd, shell=False, cwd=self.chromium_src_dir, |
771 stdout=subprocess.PIPE, stderr=subprocess.PIPE) | 782 stdout=subprocess.PIPE, stderr=subprocess.PIPE, |
| 783 env=env) |
772 out, err = p.communicate() | 784 out, err = p.communicate() |
773 return p.returncode, out, err | 785 return p.returncode, out, err |
774 | 786 |
775 def ExpandUser(self, path): | 787 def ExpandUser(self, path): |
776 # This function largely exists so it can be overridden for testing. | 788 # This function largely exists so it can be overridden for testing. |
777 return os.path.expanduser(path) | 789 return os.path.expanduser(path) |
778 | 790 |
779 def Exists(self, path): | 791 def Exists(self, path): |
780 # This function largely exists so it can be overridden for testing. | 792 # This function largely exists so it can be overridden for testing. |
781 return os.path.exists(path) | 793 return os.path.exists(path) |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
814 | 826 |
815 if __name__ == '__main__': | 827 if __name__ == '__main__': |
816 try: | 828 try: |
817 sys.exit(main(sys.argv[1:])) | 829 sys.exit(main(sys.argv[1:])) |
818 except MBErr as e: | 830 except MBErr as e: |
819 print(e) | 831 print(e) |
820 sys.exit(1) | 832 sys.exit(1) |
821 except KeyboardInterrupt: | 833 except KeyboardInterrupt: |
822 print("interrupted, exiting", stream=sys.stderr) | 834 print("interrupted, exiting", stream=sys.stderr) |
823 sys.exit(130) | 835 sys.exit(130) |
OLD | NEW |