OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright 2016 The Chromium Authors. All rights reserved. | 2 # Copyright 2016 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 """Generates an Android Studio project from a GN target.""" | 6 """Generates an Android Studio project from a GN target.""" |
7 | 7 |
8 import argparse | 8 import argparse |
9 import codecs | 9 import codecs |
10 import glob | 10 import glob |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 def Gradle(self): | 192 def Gradle(self): |
193 return self.BuildConfig()['gradle'] | 193 return self.BuildConfig()['gradle'] |
194 | 194 |
195 def Javac(self): | 195 def Javac(self): |
196 return self.BuildConfig()['javac'] | 196 return self.BuildConfig()['javac'] |
197 | 197 |
198 def GetType(self): | 198 def GetType(self): |
199 """Returns the target type from its .build_config.""" | 199 """Returns the target type from its .build_config.""" |
200 return self.DepsInfo()['type'] | 200 return self.DepsInfo()['type'] |
201 | 201 |
| 202 def IsValid(self): |
| 203 return self.GetType() in ('android_apk', 'java_library', 'java_binary') |
| 204 |
202 def ResZips(self): | 205 def ResZips(self): |
203 return self.DepsInfo().get('owned_resources_zips', []) | 206 return self.DepsInfo().get('owned_resources_zips', []) |
204 | 207 |
205 def ResDirs(self): | 208 def ResDirs(self): |
206 return self.DepsInfo().get('owned_resources_dirs', []) | 209 return self.DepsInfo().get('owned_resources_dirs', []) |
207 | 210 |
208 def JavaFiles(self): | 211 def JavaFiles(self): |
209 if self._java_files is None: | 212 if self._java_files is None: |
210 java_sources_file = self.Gradle().get('java_sources_file') | 213 java_sources_file = self.Gradle().get('java_sources_file') |
211 java_files = [] | 214 java_files = [] |
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
538 entry.android_test_entry) | 541 entry.android_test_entry) |
539 for key, value in variables['android_test'].iteritems(): | 542 for key, value in variables['android_test'].iteritems(): |
540 if isinstance(value, list): | 543 if isinstance(value, list): |
541 variables['android_test'][key] = sorted( | 544 variables['android_test'][key] = sorted( |
542 set(value) - set(variables['main'][key])) | 545 set(value) - set(variables['main'][key])) |
543 | 546 |
544 return jinja_processor.Render( | 547 return jinja_processor.Render( |
545 _TemplatePath(target_type.split('_')[0]), variables) | 548 _TemplatePath(target_type.split('_')[0]), variables) |
546 | 549 |
547 | 550 |
| 551 def _IsTestDir(path): |
| 552 return ('javatests/' in path or |
| 553 'junit/' in path or |
| 554 'test/' in path or |
| 555 'testing/' in path) |
| 556 |
| 557 |
548 def _GenerateModuleAll(gradle_output_dir, generator, build_vars, | 558 def _GenerateModuleAll(gradle_output_dir, generator, build_vars, |
549 source_properties, jinja_processor): | 559 source_properties, jinja_processor): |
550 """Returns the data for a pseudo build.gradle of all dirs. | 560 """Returns the data for a pseudo build.gradle of all dirs. |
551 | 561 |
552 See //docs/android_studio.md for more details.""" | 562 See //docs/android_studio.md for more details.""" |
553 variables = _GenerateBaseVars(generator, build_vars, source_properties) | 563 variables = _GenerateBaseVars(generator, build_vars, source_properties) |
554 target_type = 'android_apk' | 564 target_type = 'android_apk' |
555 variables['target_name'] = _MODULE_ALL | 565 variables['target_name'] = _MODULE_ALL |
556 variables['template_type'] = target_type | 566 variables['template_type'] = target_type |
557 java_dirs = sorted(generator.processed_java_dirs) | 567 java_dirs = sorted(generator.processed_java_dirs) |
558 prebuilts = sorted(generator.processed_prebuilts) | 568 prebuilts = sorted(generator.processed_prebuilts) |
559 def Relativize(paths): | 569 def Relativize(paths): |
560 return _RebasePath(paths, os.path.join(gradle_output_dir, _MODULE_ALL)) | 570 return _RebasePath(paths, os.path.join(gradle_output_dir, _MODULE_ALL)) |
| 571 main_java_dirs = [d for d in java_dirs if not _IsTestDir(d)] |
| 572 test_java_dirs = [d for d in java_dirs if _IsTestDir(d)] |
561 variables['main'] = { | 573 variables['main'] = { |
562 'android_manifest': Relativize(_DEFAULT_ANDROID_MANIFEST_PATH), | 574 'android_manifest': Relativize(_DEFAULT_ANDROID_MANIFEST_PATH), |
563 'java_dirs': Relativize(java_dirs), | 575 'java_dirs': Relativize(main_java_dirs), |
564 'prebuilts': Relativize(prebuilts), | 576 'prebuilts': Relativize(prebuilts), |
565 'java_excludes': ['**/*.java'], | 577 'java_excludes': ['**/*.java'], |
566 } | 578 } |
| 579 variables['android_test'] = { |
| 580 'java_dirs': Relativize(test_java_dirs), |
| 581 'java_excludes': ['**/*.java'], |
| 582 } |
567 data = jinja_processor.Render( | 583 data = jinja_processor.Render( |
568 _TemplatePath(target_type.split('_')[0]), variables) | 584 _TemplatePath(target_type.split('_')[0]), variables) |
569 _WriteFile( | 585 _WriteFile( |
570 os.path.join(gradle_output_dir, _MODULE_ALL, _GRADLE_BUILD_FILE), data) | 586 os.path.join(gradle_output_dir, _MODULE_ALL, _GRADLE_BUILD_FILE), data) |
571 | 587 |
572 | 588 |
573 def _GenerateRootGradle(jinja_processor): | 589 def _GenerateRootGradle(jinja_processor): |
574 """Returns the data for the root project's build.gradle.""" | 590 """Returns the data for the root project's build.gradle.""" |
575 return jinja_processor.Render(_TemplatePath('root')) | 591 return jinja_processor.Render(_TemplatePath('root')) |
576 | 592 |
577 | 593 |
578 def _GenerateSettingsGradle(project_entries): | 594 def _GenerateSettingsGradle(project_entries, add_all_module): |
579 """Returns the data for settings.gradle.""" | 595 """Returns the data for settings.gradle.""" |
580 project_name = os.path.basename(os.path.dirname(host_paths.DIR_SOURCE_ROOT)) | 596 project_name = os.path.basename(os.path.dirname(host_paths.DIR_SOURCE_ROOT)) |
581 lines = [] | 597 lines = [] |
582 lines.append('// Generated by //build/android/gradle/generate_gradle.py') | 598 lines.append('// Generated by //build/android/gradle/generate_gradle.py') |
583 lines.append('rootProject.name = "%s"' % project_name) | 599 lines.append('rootProject.name = "%s"' % project_name) |
584 lines.append('rootProject.projectDir = settingsDir') | 600 lines.append('rootProject.projectDir = settingsDir') |
585 lines.append('') | 601 lines.append('') |
586 | 602 |
587 lines.append('include ":{0}"'.format(_MODULE_ALL)) | 603 if add_all_module: |
588 lines.append( | 604 lines.append('include ":{0}"'.format(_MODULE_ALL)) |
589 'project(":{0}").projectDir = new File(settingsDir, "{0}")'.format( | 605 lines.append( |
590 _MODULE_ALL)) | 606 'project(":{0}").projectDir = new File(settingsDir, "{0}")'.format( |
| 607 _MODULE_ALL)) |
591 for entry in project_entries: | 608 for entry in project_entries: |
592 # Example target: android_webview:android_webview_java__build_config | 609 # Example target: android_webview:android_webview_java__build_config |
593 lines.append('include ":%s"' % entry.ProjectName()) | 610 lines.append('include ":%s"' % entry.ProjectName()) |
594 lines.append('project(":%s").projectDir = new File(settingsDir, "%s")' % | 611 lines.append('project(":%s").projectDir = new File(settingsDir, "%s")' % |
595 (entry.ProjectName(), entry.GradleSubdir())) | 612 (entry.ProjectName(), entry.GradleSubdir())) |
596 return '\n'.join(lines) | 613 return '\n'.join(lines) |
597 | 614 |
598 | 615 |
599 def _ExtractFile(zip_path, extracted_path): | 616 def _ExtractFile(zip_path, extracted_path): |
600 logging.info('Extracting %s to %s', zip_path, extracted_path) | 617 logging.info('Extracting %s to %s', zip_path, extracted_path) |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
690 help='Split projects by their gn deps rather than ' | 707 help='Split projects by their gn deps rather than ' |
691 'combining all the dependencies of each target') | 708 'combining all the dependencies of each target') |
692 args = parser.parse_args() | 709 args = parser.parse_args() |
693 if args.output_directory: | 710 if args.output_directory: |
694 constants.SetOutputDirectory(args.output_directory) | 711 constants.SetOutputDirectory(args.output_directory) |
695 constants.CheckOutputDirectory() | 712 constants.CheckOutputDirectory() |
696 output_dir = constants.GetOutDirectory() | 713 output_dir = constants.GetOutDirectory() |
697 devil_chromium.Initialize(output_directory=output_dir) | 714 devil_chromium.Initialize(output_directory=output_dir) |
698 run_tests_helper.SetLogLevel(args.verbose_count) | 715 run_tests_helper.SetLogLevel(args.verbose_count) |
699 | 716 |
700 # TODO(wnwen): Fix packaging so that gradle resources work in this case. | |
701 if args.split_projects: | 717 if args.split_projects: |
702 assert not args.use_gradle_process_resources, ( | 718 assert not args.use_gradle_process_resources, ( |
703 'Gradle resources does not work without --split-projects.') | 719 'Gradle resources does not work without --split-projects.') |
704 | 720 |
705 _gradle_output_dir = os.path.abspath( | 721 _gradle_output_dir = os.path.abspath( |
706 args.project_dir.replace('$CHROMIUM_OUTPUT_DIR', output_dir)) | 722 args.project_dir.replace('$CHROMIUM_OUTPUT_DIR', output_dir)) |
707 jinja_processor = jinja_template.JinjaProcessor(_FILE_DIR) | 723 jinja_processor = jinja_template.JinjaProcessor(_FILE_DIR) |
708 build_vars = _ReadPropertiesFile(os.path.join(output_dir, 'build_vars.txt')) | 724 build_vars = _ReadPropertiesFile(os.path.join(output_dir, 'build_vars.txt')) |
709 source_properties = _ReadPropertiesFile( | 725 source_properties = _ReadPropertiesFile( |
710 _RebasePath(os.path.join(build_vars['android_sdk_build_tools'], | 726 _RebasePath(os.path.join(build_vars['android_sdk_build_tools'], |
(...skipping 25 matching lines...) Expand all Loading... |
736 # when using --all. | 752 # when using --all. |
737 if args.all: | 753 if args.all: |
738 main_entries = [e for e in main_entries if ( | 754 main_entries = [e for e in main_entries if ( |
739 e.GetType() == 'android_apk' or | 755 e.GetType() == 'android_apk' or |
740 e.GnTarget().endswith('_test_apk__apk') or | 756 e.GnTarget().endswith('_test_apk__apk') or |
741 e.GnTarget().endswith('_junit_tests__java_binary'))] | 757 e.GnTarget().endswith('_junit_tests__java_binary'))] |
742 | 758 |
743 if args.split_projects: | 759 if args.split_projects: |
744 main_entries = _FindAllProjectEntries(main_entries) | 760 main_entries = _FindAllProjectEntries(main_entries) |
745 logging.info('Found %d dependent build_config targets.', len(main_entries)) | 761 logging.info('Found %d dependent build_config targets.', len(main_entries)) |
746 entries = _CombineTestEntries(main_entries) | 762 |
| 763 entries = [e for e in _CombineTestEntries(main_entries) if e.IsValid()] |
747 logging.info('Creating %d projects for targets.', len(entries)) | 764 logging.info('Creating %d projects for targets.', len(entries)) |
748 | 765 |
| 766 # When only one entry will be generated we want it to have a valid |
| 767 # build.gradle file with its own AndroidManifest. |
| 768 add_all_module = not args.split_projects and len(entries) > 1 |
| 769 |
749 logging.warning('Writing .gradle files...') | 770 logging.warning('Writing .gradle files...') |
750 project_entries = [] | 771 project_entries = [] |
751 zip_tuples = [] | 772 zip_tuples = [] |
752 generated_inputs = [] | 773 generated_inputs = [] |
753 for entry in entries: | 774 for entry in entries: |
754 if entry.GetType() not in ('android_apk', 'java_library', 'java_binary'): | |
755 continue | |
756 | |
757 data = _GenerateGradleFile(entry, generator, build_vars, source_properties, | 775 data = _GenerateGradleFile(entry, generator, build_vars, source_properties, |
758 jinja_processor) | 776 jinja_processor) |
759 if data: | 777 if data: |
760 project_entries.append(entry) | |
761 # Build all paths references by .gradle that exist within output_dir. | 778 # Build all paths references by .gradle that exist within output_dir. |
762 generated_inputs.extend(generator.GeneratedInputs(entry)) | 779 generated_inputs.extend(generator.GeneratedInputs(entry)) |
763 zip_tuples.extend( | 780 zip_tuples.extend( |
764 (s, os.path.join(generator.EntryOutputDir(entry), _SRCJARS_SUBDIR)) | 781 (s, os.path.join(generator.EntryOutputDir(entry), _SRCJARS_SUBDIR)) |
765 for s in generator.AllSrcjars(entry)) | 782 for s in generator.AllSrcjars(entry)) |
766 zip_tuples.extend( | 783 zip_tuples.extend( |
767 (s, os.path.join(generator.EntryOutputDir(entry), _RES_SUBDIR)) | 784 (s, os.path.join(generator.EntryOutputDir(entry), _RES_SUBDIR)) |
768 for s in generator.AllResZips(entry)) | 785 for s in generator.AllResZips(entry)) |
769 _WriteFile( | 786 if not add_all_module: |
770 os.path.join(generator.EntryOutputDir(entry), _GRADLE_BUILD_FILE), | 787 project_entries.append(entry) |
771 data) | 788 _WriteFile( |
| 789 os.path.join(generator.EntryOutputDir(entry), _GRADLE_BUILD_FILE), |
| 790 data) |
772 | 791 |
773 _GenerateModuleAll(_gradle_output_dir, generator, build_vars, | 792 if add_all_module: |
774 source_properties, jinja_processor) | 793 _GenerateModuleAll(_gradle_output_dir, generator, build_vars, |
| 794 source_properties, jinja_processor) |
775 | 795 |
776 _WriteFile(os.path.join(generator.project_dir, _GRADLE_BUILD_FILE), | 796 _WriteFile(os.path.join(generator.project_dir, _GRADLE_BUILD_FILE), |
777 _GenerateRootGradle(jinja_processor)) | 797 _GenerateRootGradle(jinja_processor)) |
778 | 798 |
779 _WriteFile(os.path.join(generator.project_dir, 'settings.gradle'), | 799 _WriteFile(os.path.join(generator.project_dir, 'settings.gradle'), |
780 _GenerateSettingsGradle(project_entries)) | 800 _GenerateSettingsGradle(project_entries, add_all_module)) |
781 | 801 |
782 sdk_path = _RebasePath(build_vars['android_sdk_root']) | 802 sdk_path = _RebasePath(build_vars['android_sdk_root']) |
783 _WriteFile(os.path.join(generator.project_dir, 'local.properties'), | 803 _WriteFile(os.path.join(generator.project_dir, 'local.properties'), |
784 _GenerateLocalProperties(sdk_path)) | 804 _GenerateLocalProperties(sdk_path)) |
785 | 805 |
786 if generated_inputs: | 806 if generated_inputs: |
787 logging.warning('Building generated source files...') | 807 logging.warning('Building generated source files...') |
788 targets = _RebasePath(generated_inputs, output_dir) | 808 targets = _RebasePath(generated_inputs, output_dir) |
789 _RunNinja(output_dir, targets) | 809 _RunNinja(output_dir, targets) |
790 | 810 |
791 if zip_tuples: | 811 if zip_tuples: |
792 _ExtractZips(generator.project_dir, zip_tuples) | 812 _ExtractZips(generator.project_dir, zip_tuples) |
793 | 813 |
794 logging.warning('Project created! (%d subprojects)', len(project_entries)) | 814 logging.warning('Project created!') |
795 logging.warning('Generated projects work with Android Studio 2.3') | 815 logging.warning('Generated projects work with Android Studio 2.3') |
796 logging.warning('For more tips: https://chromium.googlesource.com/chromium' | 816 logging.warning('For more tips: https://chromium.googlesource.com/chromium' |
797 '/src.git/+/master/docs/android_studio.md') | 817 '/src.git/+/master/docs/android_studio.md') |
798 | 818 |
799 | 819 |
800 if __name__ == '__main__': | 820 if __name__ == '__main__': |
801 main() | 821 main() |
OLD | NEW |