| 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 755 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 766 env['GYP_CROSSCOMPILE'] = '1' | 766 env['GYP_CROSSCOMPILE'] = '1' |
| 767 return cmd, env | 767 return cmd, env |
| 768 | 768 |
| 769 def RunGNAnalyze(self, vals): | 769 def RunGNAnalyze(self, vals): |
| 770 # analyze runs before 'gn gen' now, so we need to run gn gen | 770 # analyze runs before 'gn gen' now, so we need to run gn gen |
| 771 # in order to ensure that we have a build directory. | 771 # in order to ensure that we have a build directory. |
| 772 ret = self.RunGNGen(vals) | 772 ret = self.RunGNGen(vals) |
| 773 if ret: | 773 if ret: |
| 774 return ret | 774 return ret |
| 775 | 775 |
| 776 inp = self.ReadInputJSON(['files', 'targets']) | 776 # TODO(dpranke): add 'test_targets' and 'additional_compile_targets' |
| 777 # as required keys once the recipe has been converted over. |
| 778 # See crbug.com/552146. |
| 779 inp = self.ReadInputJSON(['files']) |
| 777 if self.args.verbose: | 780 if self.args.verbose: |
| 778 self.Print() | 781 self.Print() |
| 779 self.Print('analyze input:') | 782 self.Print('analyze input:') |
| 780 self.PrintJSON(inp) | 783 self.PrintJSON(inp) |
| 781 self.Print() | 784 self.Print() |
| 782 | 785 |
| 786 use_new_logic = ('test_targets' in inp and |
| 787 'additional_compile_targets' in inp) |
| 788 if use_new_logic: |
| 789 # TODO(crbug.com/555273) - currently GN treats targets and |
| 790 # additional_compile_targets identically since we can't tell the |
| 791 # difference between a target that is a group in GN and one that isn't. |
| 792 # We should eventually fix this and treat the two types differently. |
| 793 targets = (set(inp['test_targets']) | |
| 794 set(inp['additional_compile_targets'])) |
| 795 else: |
| 796 targets = set(inp['targets']) |
| 797 |
| 783 output_path = self.args.output_path[0] | 798 output_path = self.args.output_path[0] |
| 784 | 799 |
| 785 # Bail out early if a GN file was modified, since 'gn refs' won't know | 800 # Bail out early if a GN file was modified, since 'gn refs' won't know |
| 786 # what to do about it. | 801 # what to do about it. Also, bail out early if 'all' was asked for, |
| 787 if any(f.endswith('.gn') or f.endswith('.gni') for f in inp['files']): | 802 # since we can't deal with it yet. |
| 788 self.WriteJSON({'status': 'Found dependency (all)'}, output_path) | 803 if (any(f.endswith('.gn') or f.endswith('.gni') for f in inp['files']) or |
| 789 return 0 | 804 'all' in targets): |
| 790 | 805 if use_new_logic: |
| 791 # Bail out early if 'all' was asked for, since 'gn refs' won't recognize it. | 806 self.WriteJSON({ |
| 792 if 'all' in inp['targets']: | 807 'status': 'Found dependency (all)', |
| 793 self.WriteJSON({'status': 'Found dependency (all)'}, output_path) | 808 'compile_targets': sorted(targets), |
| 809 'test_targets': sorted(targets & set(inp['test_targets'])), |
| 810 }, output_path) |
| 811 else: |
| 812 self.WriteJSON({'status': 'Found dependency (all)'}, output_path) |
| 794 return 0 | 813 return 0 |
| 795 | 814 |
| 796 # This shouldn't normally happen, but could due to unusual race conditions, | 815 # This shouldn't normally happen, but could due to unusual race conditions, |
| 797 # like a try job that gets scheduled before a patch lands but runs after | 816 # like a try job that gets scheduled before a patch lands but runs after |
| 798 # the patch has landed. | 817 # the patch has landed. |
| 799 if not inp['files']: | 818 if not inp['files']: |
| 800 self.Print('Warning: No files modified in patch, bailing out early.') | 819 self.Print('Warning: No files modified in patch, bailing out early.') |
| 801 self.WriteJSON({'targets': [], | 820 if use_new_logic: |
| 802 'build_targets': [], | 821 self.WriteJSON({ |
| 803 'status': 'No dependency'}, output_path) | 822 'status': 'No dependency', |
| 823 'compile_targets': [], |
| 824 'test_targets': [], |
| 825 }, output_path) |
| 826 else: |
| 827 self.WriteJSON({ |
| 828 'status': 'No dependency', |
| 829 'targets': [], |
| 830 'build_targets': [], |
| 831 }, output_path) |
| 804 return 0 | 832 return 0 |
| 805 | 833 |
| 806 ret = 0 | 834 ret = 0 |
| 807 response_file = self.TempFile() | 835 response_file = self.TempFile() |
| 808 response_file.write('\n'.join(inp['files']) + '\n') | 836 response_file.write('\n'.join(inp['files']) + '\n') |
| 809 response_file.close() | 837 response_file.close() |
| 810 | 838 |
| 811 matching_targets = [] | 839 matching_targets = set() |
| 812 try: | 840 try: |
| 813 cmd = self.GNCmd('refs', self.args.path[0]) + [ | 841 cmd = self.GNCmd('refs', self.args.path[0]) + [ |
| 814 '@%s' % response_file.name, '--all', '--as=output'] | 842 '@%s' % response_file.name, '--all', '--as=output'] |
| 815 ret, out, _ = self.Run(cmd, force_verbose=False) | 843 ret, out, _ = self.Run(cmd, force_verbose=False) |
| 816 if ret and not 'The input matches no targets' in out: | 844 if ret and not 'The input matches no targets' in out: |
| 817 self.WriteFailureAndRaise('gn refs returned %d: %s' % (ret, out), | 845 self.WriteFailureAndRaise('gn refs returned %d: %s' % (ret, out), |
| 818 output_path) | 846 output_path) |
| 819 build_dir = self.ToSrcRelPath(self.args.path[0]) + self.sep | 847 build_dir = self.ToSrcRelPath(self.args.path[0]) + self.sep |
| 820 for output in out.splitlines(): | 848 for output in out.splitlines(): |
| 821 build_output = output.replace(build_dir, '') | 849 build_output = output.replace(build_dir, '') |
| 822 if build_output in inp['targets']: | 850 if build_output in targets: |
| 823 matching_targets.append(build_output) | 851 matching_targets.add(build_output) |
| 824 | 852 |
| 825 cmd = self.GNCmd('refs', self.args.path[0]) + [ | 853 cmd = self.GNCmd('refs', self.args.path[0]) + [ |
| 826 '@%s' % response_file.name, '--all'] | 854 '@%s' % response_file.name, '--all'] |
| 827 ret, out, _ = self.Run(cmd, force_verbose=False) | 855 ret, out, _ = self.Run(cmd, force_verbose=False) |
| 828 if ret and not 'The input matches no targets' in out: | 856 if ret and not 'The input matches no targets' in out: |
| 829 self.WriteFailureAndRaise('gn refs returned %d: %s' % (ret, out), | 857 self.WriteFailureAndRaise('gn refs returned %d: %s' % (ret, out), |
| 830 output_path) | 858 output_path) |
| 831 for label in out.splitlines(): | 859 for label in out.splitlines(): |
| 832 build_target = label[2:] | 860 build_target = label[2:] |
| 833 # We want to accept 'chrome/android:chrome_public_apk' and | 861 # We want to accept 'chrome/android:chrome_public_apk' and |
| 834 # just 'chrome_public_apk'. This may result in too many targets | 862 # just 'chrome_public_apk'. This may result in too many targets |
| 835 # getting built, but we can adjust that later if need be. | 863 # getting built, but we can adjust that later if need be. |
| 836 for input_target in inp['targets']: | 864 for input_target in targets: |
| 837 if (input_target == build_target or | 865 if (input_target == build_target or |
| 838 build_target.endswith(':' + input_target)): | 866 build_target.endswith(':' + input_target)): |
| 839 matching_targets.append(input_target) | 867 matching_targets.add(input_target) |
| 840 finally: | 868 finally: |
| 841 self.RemoveFile(response_file.name) | 869 self.RemoveFile(response_file.name) |
| 842 | 870 |
| 843 if matching_targets: | 871 if matching_targets: |
| 844 # TODO: it could be that a target X might depend on a target Y | 872 if use_new_logic: |
| 845 # and both would be listed in the input, but we would only need | 873 self.WriteJSON({ |
| 846 # to specify target X as a build_target (whereas both X and Y are | 874 'status': 'Found dependency', |
| 847 # targets). I'm not sure if that optimization is generally worth it. | 875 'compile_targets': sorted(matching_targets), |
| 848 self.WriteJSON({'targets': sorted(set(matching_targets)), | 876 'test_targets': sorted(matching_targets & |
| 849 'build_targets': sorted(set(matching_targets)), | 877 set(inp['test_targets'])), |
| 850 'status': 'Found dependency'}, output_path) | 878 }, output_path) |
| 879 else: |
| 880 self.WriteJSON({ |
| 881 'status': 'Found dependency', |
| 882 'targets': sorted(matching_targets), |
| 883 'build_targets': sorted(matching_targets), |
| 884 }, output_path) |
| 851 else: | 885 else: |
| 852 self.WriteJSON({'targets': [], | 886 if use_new_logic: |
| 853 'build_targets': [], | 887 self.WriteJSON({ |
| 854 'status': 'No dependency'}, output_path) | 888 'status': 'No dependency', |
| 889 'compile_targets': [], |
| 890 'test_targets': [], |
| 891 }, output_path) |
| 892 else: |
| 893 self.WriteJSON({ |
| 894 'status': 'No dependency', |
| 895 'targets': [], |
| 896 'build_targets': [], |
| 897 }, output_path) |
| 855 | 898 |
| 856 if self.args.verbose: | 899 if self.args.verbose: |
| 857 outp = json.loads(self.ReadFile(output_path)) | 900 outp = json.loads(self.ReadFile(output_path)) |
| 858 self.Print() | 901 self.Print() |
| 859 self.Print('analyze output:') | 902 self.Print('analyze output:') |
| 860 self.PrintJSON(outp) | 903 self.PrintJSON(outp) |
| 861 self.Print() | 904 self.Print() |
| 862 | 905 |
| 863 return 0 | 906 return 0 |
| 864 | 907 |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1047 | 1090 |
| 1048 if __name__ == '__main__': | 1091 if __name__ == '__main__': |
| 1049 try: | 1092 try: |
| 1050 sys.exit(main(sys.argv[1:])) | 1093 sys.exit(main(sys.argv[1:])) |
| 1051 except MBErr as e: | 1094 except MBErr as e: |
| 1052 print(e) | 1095 print(e) |
| 1053 sys.exit(1) | 1096 sys.exit(1) |
| 1054 except KeyboardInterrupt: | 1097 except KeyboardInterrupt: |
| 1055 print("interrupted, exiting", stream=sys.stderr) | 1098 print("interrupted, exiting", stream=sys.stderr) |
| 1056 sys.exit(130) | 1099 sys.exit(130) |
| OLD | NEW |