Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(462)

Side by Side Diff: build/android/gradle/generate_gradle.py

Issue 2812133003: Android: Add pseudo module for Android Studio (Closed)
Patch Set: Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « build/android/gradle/android.jinja ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 17 matching lines...) Expand all
28 from util import build_utils 28 from util import build_utils
29 29
30 30
31 _DEFAULT_ANDROID_MANIFEST_PATH = os.path.join( 31 _DEFAULT_ANDROID_MANIFEST_PATH = os.path.join(
32 host_paths.DIR_SOURCE_ROOT, 'build', 'android', 'AndroidManifest.xml') 32 host_paths.DIR_SOURCE_ROOT, 'build', 'android', 'AndroidManifest.xml')
33 _FILE_DIR = os.path.dirname(__file__) 33 _FILE_DIR = os.path.dirname(__file__)
34 _SRCJARS_SUBDIR = 'extracted-srcjars' 34 _SRCJARS_SUBDIR = 'extracted-srcjars'
35 _JNI_LIBS_SUBDIR = 'symlinked-libs' 35 _JNI_LIBS_SUBDIR = 'symlinked-libs'
36 _ARMEABI_SUBDIR = 'armeabi' 36 _ARMEABI_SUBDIR = 'armeabi'
37 _RES_SUBDIR = 'extracted-res' 37 _RES_SUBDIR = 'extracted-res'
38 _GRADLE_BUILD_FILE = 'build.gradle'
39 _PSEUDO_NAME = 'a_pseudo_module'
agrieve 2017/04/12 19:36:29 nit: is the "a" need to be there so it comes alpha
Peter Wen 2017/04/13 17:23:16 Added comment, changed to _all
38 40
39 _DEFAULT_TARGETS = [ 41 _DEFAULT_TARGETS = [
40 # TODO(agrieve): .build_config seem not quite right for this target 42 # TODO(agrieve): .build_config seem not quite right for this target
41 # because it has resources as deps of android_apk() rather than using an 43 # because it has resources as deps of android_apk() rather than using an
42 # android_library() intermediate target. 44 # android_library() intermediate target.
43 # '//android_webview:system_webview_apk', 45 # '//android_webview:system_webview_apk',
44 '//android_webview/test:android_webview_apk', 46 '//android_webview/test:android_webview_apk',
45 '//android_webview/test:android_webview_test_apk', 47 '//android_webview/test:android_webview_test_apk',
46 '//base:base_junit_tests', 48 '//base:base_junit_tests',
47 '//chrome/android:chrome_junit_tests', 49 '//chrome/android:chrome_junit_tests',
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
230 for p in self.Gradle()['dependent_java_projects']) 232 for p in self.Gradle()['dependent_java_projects'])
231 all_entries = set() 233 all_entries = set()
232 for dep in deps: 234 for dep in deps:
233 all_entries.update(dep.AllEntries()) 235 all_entries.update(dep.AllEntries())
234 all_entries.add(self) 236 all_entries.add(self)
235 self._all_entries = list(all_entries) 237 self._all_entries = list(all_entries)
236 return self._all_entries 238 return self._all_entries
237 239
238 240
239 class _ProjectContextGenerator(object): 241 class _ProjectContextGenerator(object):
242
243 java_dirs = set()
agrieve 2017/04/12 19:36:29 This is a singleton class, so it's a bit confusing
Peter Wen 2017/04/13 17:23:17 Done.
244 prebuilts = set()
245
240 """Helper class to generate gradle build files""" 246 """Helper class to generate gradle build files"""
241 def __init__(self, project_dir, build_vars, use_gradle_process_resources, 247 def __init__(self, project_dir, build_vars, use_gradle_process_resources,
242 jinja_processor, split_projects): 248 jinja_processor, split_projects):
243 self.project_dir = project_dir 249 self.project_dir = project_dir
244 self.build_vars = build_vars 250 self.build_vars = build_vars
245 self.use_gradle_process_resources = use_gradle_process_resources 251 self.use_gradle_process_resources = use_gradle_process_resources
246 self.jinja_processor = jinja_processor 252 self.jinja_processor = jinja_processor
247 self.split_projects = split_projects 253 self.split_projects = split_projects
248 254
249 def _GenJniLibs(self, root_entry): 255 def _GenJniLibs(self, root_entry):
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
327 for entry in self._GetEntries(root_entry): 333 for entry in self._GetEntries(root_entry):
328 generated_inputs.update(entry.GeneratedJavaFiles()) 334 generated_inputs.update(entry.GeneratedJavaFiles())
329 generated_inputs.update(entry.PrebuiltJars()) 335 generated_inputs.update(entry.PrebuiltJars())
330 return set(generated_inputs) 336 return set(generated_inputs)
331 337
332 def Generate(self, root_entry): 338 def Generate(self, root_entry):
333 # TODO(agrieve): Add an option to use interface jars and see if that speeds 339 # TODO(agrieve): Add an option to use interface jars and see if that speeds
334 # things up at all. 340 # things up at all.
335 variables = {} 341 variables = {}
336 java_dirs, excludes = self._GenJavaDirs(root_entry) 342 java_dirs, excludes = self._GenJavaDirs(root_entry)
343 java_dirs.append(
344 os.path.join(self.EntryOutputDir(root_entry), _SRCJARS_SUBDIR))
345 self.java_dirs.update(java_dirs)
337 java_dirs.sort() 346 java_dirs.sort()
338 variables['java_dirs'] = self._Relativize(root_entry, java_dirs) 347 variables['java_dirs'] = self._Relativize(root_entry, java_dirs)
339 variables['java_dirs'].append(_SRCJARS_SUBDIR)
340 variables['java_excludes'] = excludes 348 variables['java_excludes'] = excludes
341 variables['jni_libs'] = self._Relativize( 349 variables['jni_libs'] = self._Relativize(
342 root_entry, set(self._GenJniLibs(root_entry))) 350 root_entry, set(self._GenJniLibs(root_entry)))
343 variables['prebuilts'] = [ 351 variables['prebuilts'] = [
344 p for e in self._GetEntries(root_entry) for p in e.PrebuiltJars()] 352 p for e in self._GetEntries(root_entry) for p in e.PrebuiltJars()]
353 self.prebuilts.update(variables['prebuilts'])
345 variables['res_dirs'] = [ 354 variables['res_dirs'] = [
346 p for e in self._GetEntries(root_entry) for p in e.ResDirs()] 355 p for e in self._GetEntries(root_entry) for p in e.ResDirs()]
347 for entry in self._GetEntries(root_entry): 356 for entry in self._GetEntries(root_entry):
348 variables['prebuilts'] += entry.PrebuiltJars() 357 variables['prebuilts'] += entry.PrebuiltJars()
349 variables['res_dirs'] += entry.ResDirs() 358 variables['res_dirs'] += entry.ResDirs()
350 variables['prebuilts'] = self._Relativize( 359 variables['prebuilts'] = self._Relativize(
351 root_entry, set(variables['prebuilts'])) 360 root_entry, set(variables['prebuilts']))
352 variables['res_dirs'] = self._Relativize( 361 variables['res_dirs'] = self._Relativize(
353 root_entry, set(variables['res_dirs'])) 362 root_entry, set(variables['res_dirs']))
354 variables['res_dirs'].append(_RES_SUBDIR) 363 variables['res_dirs'].append(_RES_SUBDIR)
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
531 entry.android_test_entry) 540 entry.android_test_entry)
532 for key, value in variables['android_test'].iteritems(): 541 for key, value in variables['android_test'].iteritems():
533 if isinstance(value, list): 542 if isinstance(value, list):
534 variables['android_test'][key] = list( 543 variables['android_test'][key] = list(
535 set(value) - set(variables['main'][key])) 544 set(value) - set(variables['main'][key]))
536 545
537 return jinja_processor.Render( 546 return jinja_processor.Render(
538 _TemplatePath(target_type.split('_')[0]), variables) 547 _TemplatePath(target_type.split('_')[0]), variables)
539 548
540 549
550 def _GeneratePseudoModule(gradle_output_dir, generator, build_vars,
551 jinja_processor):
552 """Returns the data for a pseudo build.gradle of all dirs."""
agrieve 2017/04/12 19:36:29 what makes it pseudo? Is it not a real module? May
Peter Wen 2017/04/13 17:23:17 Changed name to "All"
553
554 variables = {
555 'sourceSetName': 'main',
556 'depCompileName': 'compile',
557 'target_name': _PSEUDO_NAME,
558 }
559 target_type = 'android_apk'
560 variables['template_type'] = target_type
561 variables['use_gradle_process_resources'] = (
562 generator.use_gradle_process_resources)
563 source_properties = _ReadPropertiesFile(
agrieve 2017/04/12 19:36:29 Please figure out how to re-use rather than copy &
Peter Wen 2017/04/13 17:23:17 Done.
564 _RebasePath(os.path.join(build_vars['android_sdk_build_tools'],
565 'source.properties')))
566 variables['build_tools_version'] = source_properties['Pkg.Revision']
567 variables['compile_sdk_version'] = (
568 'android-%s' % build_vars['android_sdk_version'])
569 def Relativize(paths):
570 return _RebasePath(paths, os.path.join(gradle_output_dir, _PSEUDO_NAME))
571 java_dirs = list(_ProjectContextGenerator.java_dirs)
572 java_dirs.sort()
573 prebuilts = list(_ProjectContextGenerator.prebuilts)
574 prebuilts.sort()
575 variables['main'] = {
576 'android_manifest': Relativize(_DEFAULT_ANDROID_MANIFEST_PATH),
577 'java_dirs': Relativize(java_dirs),
578 'prebuilts': Relativize(prebuilts),
579 'java_excludes': ['**/*.java'],
580 # TODO(wnwen): exclude everything
581 }
582 data = jinja_processor.Render(
583 _TemplatePath(target_type.split('_')[0]), variables)
584 _WriteFile(
585 os.path.join(gradle_output_dir, _PSEUDO_NAME, _GRADLE_BUILD_FILE), data)
586
587
541 def _GenerateRootGradle(jinja_processor): 588 def _GenerateRootGradle(jinja_processor):
542 """Returns the data for the root project's build.gradle.""" 589 """Returns the data for the root project's build.gradle."""
543 return jinja_processor.Render(_TemplatePath('root')) 590 return jinja_processor.Render(_TemplatePath('root'))
544 591
545 592
546 def _GenerateSettingsGradle(project_entries): 593 def _GenerateSettingsGradle(project_entries, avoid_pseudo_module):
547 """Returns the data for settings.gradle.""" 594 """Returns the data for settings.gradle."""
548 project_name = os.path.basename(os.path.dirname(host_paths.DIR_SOURCE_ROOT)) 595 project_name = os.path.basename(os.path.dirname(host_paths.DIR_SOURCE_ROOT))
549 lines = [] 596 lines = []
550 lines.append('// Generated by //build/android/gradle/generate_gradle.py') 597 lines.append('// Generated by //build/android/gradle/generate_gradle.py')
551 lines.append('rootProject.name = "%s"' % project_name) 598 lines.append('rootProject.name = "%s"' % project_name)
552 lines.append('rootProject.projectDir = settingsDir') 599 lines.append('rootProject.projectDir = settingsDir')
553 lines.append('') 600 lines.append('')
554 601
602 if not avoid_pseudo_module:
603 lines.append('include ":{0}"'.format(_PSEUDO_NAME))
604 lines.append(
605 'project(":{0}").projectDir = new File(settingsDir, "{0}")'.format(
606 _PSEUDO_NAME))
555 for entry in project_entries: 607 for entry in project_entries:
556 # Example target: android_webview:android_webview_java__build_config 608 # Example target: android_webview:android_webview_java__build_config
557 lines.append('include ":%s"' % entry.ProjectName()) 609 lines.append('include ":%s"' % entry.ProjectName())
558 lines.append('project(":%s").projectDir = new File(settingsDir, "%s")' % 610 lines.append('project(":%s").projectDir = new File(settingsDir, "%s")' %
559 (entry.ProjectName(), entry.GradleSubdir())) 611 (entry.ProjectName(), entry.GradleSubdir()))
560 return '\n'.join(lines) 612 return '\n'.join(lines)
561 613
562 614
563 def _ExtractFile(zip_path, extracted_path): 615 def _ExtractFile(zip_path, extracted_path):
564 logging.info('Extracting %s to %s', zip_path, extracted_path) 616 logging.info('Extracting %s to %s', zip_path, extracted_path)
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
646 parser.add_argument('--all', 698 parser.add_argument('--all',
647 action='store_true', 699 action='store_true',
648 help='Generate all java targets (slows down IDE)') 700 help='Generate all java targets (slows down IDE)')
649 parser.add_argument('--use-gradle-process-resources', 701 parser.add_argument('--use-gradle-process-resources',
650 action='store_true', 702 action='store_true',
651 help='Have gradle generate R.java rather than ninja') 703 help='Have gradle generate R.java rather than ninja')
652 parser.add_argument('--split-projects', 704 parser.add_argument('--split-projects',
653 action='store_true', 705 action='store_true',
654 help='Split projects by their gn deps rather than ' 706 help='Split projects by their gn deps rather than '
655 'combining all the dependencies of each target') 707 'combining all the dependencies of each target')
708 parser.add_argument('--avoid-pseudo-module',
709 action='store_true',
710 help='Prevent an overall pseudo module from being '
agrieve 2017/04/12 19:36:29 Please explain why you might ever want to do this
Peter Wen 2017/04/13 17:23:16 Removed. Hmm... just an escape hatch I added, not
711 'generated (not applicable to split projects)')
656 args = parser.parse_args() 712 args = parser.parse_args()
657 if args.output_directory: 713 if args.output_directory:
658 constants.SetOutputDirectory(args.output_directory) 714 constants.SetOutputDirectory(args.output_directory)
659 constants.CheckOutputDirectory() 715 constants.CheckOutputDirectory()
660 output_dir = constants.GetOutDirectory() 716 output_dir = constants.GetOutDirectory()
661 devil_chromium.Initialize(output_directory=output_dir) 717 devil_chromium.Initialize(output_directory=output_dir)
662 run_tests_helper.SetLogLevel(args.verbose_count) 718 run_tests_helper.SetLogLevel(args.verbose_count)
663 719
664 # TODO(wnwen): Fix packaging so that gradle resources work in this case. 720 # TODO(wnwen): Fix packaging so that gradle resources work in this case.
665 if args.use_gradle_process_resources: 721 if args.split_projects:
666 assert args.split_projects, ( 722 args.avoid_pseudo_module = True
667 'Gradle resources does not yet work without --split-projects.') 723 assert not args.use_gradle_process_resources, (
724 'Gradle resources does not work without --split-projects.')
668 725
669 _gradle_output_dir = os.path.abspath( 726 _gradle_output_dir = os.path.abspath(
670 args.project_dir.replace('$CHROMIUM_OUTPUT_DIR', output_dir)) 727 args.project_dir.replace('$CHROMIUM_OUTPUT_DIR', output_dir))
671 jinja_processor = jinja_template.JinjaProcessor(_FILE_DIR) 728 jinja_processor = jinja_template.JinjaProcessor(_FILE_DIR)
672 build_vars = _ReadPropertiesFile(os.path.join(output_dir, 'build_vars.txt')) 729 build_vars = _ReadPropertiesFile(os.path.join(output_dir, 'build_vars.txt'))
673 generator = _ProjectContextGenerator(_gradle_output_dir, build_vars, 730 generator = _ProjectContextGenerator(_gradle_output_dir, build_vars,
674 args.use_gradle_process_resources, jinja_processor, args.split_projects) 731 args.use_gradle_process_resources, jinja_processor, args.split_projects)
675 logging.warning('Creating project at: %s', generator.project_dir) 732 logging.warning('Creating project at: %s', generator.project_dir)
676 733
677 if args.all: 734 if args.all:
(...skipping 11 matching lines...) Expand all
689 for t in targets] 746 for t in targets]
690 747
691 main_entries = [_ProjectEntry.FromGnTarget(t) for t in targets] 748 main_entries = [_ProjectEntry.FromGnTarget(t) for t in targets]
692 749
693 logging.warning('Building .build_config files...') 750 logging.warning('Building .build_config files...')
694 _RunNinja(output_dir, [e.NinjaBuildConfigTarget() for e in main_entries]) 751 _RunNinja(output_dir, [e.NinjaBuildConfigTarget() for e in main_entries])
695 752
696 # There are many unused libraries, so restrict to those that are actually used 753 # There are many unused libraries, so restrict to those that are actually used
697 # when using --all. 754 # when using --all.
698 if args.all: 755 if args.all:
699 main_entries = [e for e in main_entries if e.GetType() == 'android_apk'] 756 main_entries = [e for e in main_entries if (
757 e.GetType() == 'android_apk' or
758 e.GnTarget().endswith('_test_apk__apk') or
759 e.GnTarget().endswith('_junit_tests__java_binary'))]
700 760
701 if args.split_projects: 761 if args.split_projects:
702 main_entries = _FindAllProjectEntries(main_entries) 762 main_entries = _FindAllProjectEntries(main_entries)
703 logging.info('Found %d dependent build_config targets.', len(main_entries)) 763 logging.info('Found %d dependent build_config targets.', len(main_entries))
704 entries = _CombineTestEntries(main_entries) 764 entries = _CombineTestEntries(main_entries)
705 logging.info('Creating %d projects for targets.', len(entries)) 765 logging.info('Creating %d projects for targets.', len(entries))
706 766
707 logging.warning('Writing .gradle files...') 767 logging.warning('Writing .gradle files...')
708 project_entries = [] 768 project_entries = []
709 zip_tuples = [] 769 zip_tuples = []
710 generated_inputs = [] 770 generated_inputs = []
711 for entry in entries: 771 for entry in entries:
712 if entry.GetType() not in ('android_apk', 'java_library', 'java_binary'): 772 if entry.GetType() not in ('android_apk', 'java_library', 'java_binary'):
713 continue 773 continue
714 774
715 data = _GenerateGradleFile(entry, generator, build_vars, jinja_processor) 775 data = _GenerateGradleFile(entry, generator, build_vars, jinja_processor)
716 if data: 776 if data:
717 project_entries.append(entry) 777 project_entries.append(entry)
718 # Build all paths references by .gradle that exist within output_dir. 778 # Build all paths references by .gradle that exist within output_dir.
719 generated_inputs.extend(generator.GeneratedInputs(entry)) 779 generated_inputs.extend(generator.GeneratedInputs(entry))
720 zip_tuples.extend( 780 zip_tuples.extend(
721 (s, os.path.join(generator.EntryOutputDir(entry), _SRCJARS_SUBDIR)) 781 (s, os.path.join(generator.EntryOutputDir(entry), _SRCJARS_SUBDIR))
722 for s in generator.AllSrcjars(entry)) 782 for s in generator.AllSrcjars(entry))
723 zip_tuples.extend( 783 zip_tuples.extend(
724 (s, os.path.join(generator.EntryOutputDir(entry), _RES_SUBDIR)) 784 (s, os.path.join(generator.EntryOutputDir(entry), _RES_SUBDIR))
725 for s in generator.AllResZips(entry)) 785 for s in generator.AllResZips(entry))
726 _WriteFile( 786 _WriteFile(
727 os.path.join(generator.EntryOutputDir(entry), 'build.gradle'), data) 787 os.path.join(generator.EntryOutputDir(entry), _GRADLE_BUILD_FILE),
788 data)
728 789
729 _WriteFile(os.path.join(generator.project_dir, 'build.gradle'), 790 if not args.avoid_pseudo_module:
791 _GeneratePseudoModule(
792 _gradle_output_dir, generator, build_vars, jinja_processor)
793
794 _WriteFile(os.path.join(generator.project_dir, _GRADLE_BUILD_FILE),
730 _GenerateRootGradle(jinja_processor)) 795 _GenerateRootGradle(jinja_processor))
731 796
732 _WriteFile(os.path.join(generator.project_dir, 'settings.gradle'), 797 _WriteFile(os.path.join(generator.project_dir, 'settings.gradle'),
733 _GenerateSettingsGradle(project_entries)) 798 _GenerateSettingsGradle(project_entries, args.avoid_pseudo_module))
734 799
735 sdk_path = _RebasePath(build_vars['android_sdk_root']) 800 sdk_path = _RebasePath(build_vars['android_sdk_root'])
736 _WriteFile(os.path.join(generator.project_dir, 'local.properties'), 801 _WriteFile(os.path.join(generator.project_dir, 'local.properties'),
737 _GenerateLocalProperties(sdk_path)) 802 _GenerateLocalProperties(sdk_path))
738 803
739 if generated_inputs: 804 if generated_inputs:
740 logging.warning('Building generated source files...') 805 logging.warning('Building generated source files...')
741 targets = _RebasePath(generated_inputs, output_dir) 806 targets = _RebasePath(generated_inputs, output_dir)
742 _RunNinja(output_dir, targets) 807 _RunNinja(output_dir, targets)
743 808
744 if zip_tuples: 809 if zip_tuples:
745 _ExtractZips(generator.project_dir, zip_tuples) 810 _ExtractZips(generator.project_dir, zip_tuples)
746 811
747 logging.warning('Project created! (%d subprojects)', len(project_entries)) 812 logging.warning('Project created! (%d subprojects)', len(project_entries))
748 logging.warning('Generated projects work with Android Studio 2.3') 813 logging.warning('Generated projects work with Android Studio 2.3')
749 logging.warning('For more tips: https://chromium.googlesource.com/chromium' 814 logging.warning('For more tips: https://chromium.googlesource.com/chromium'
750 '/src.git/+/master/docs/android_studio.md') 815 '/src.git/+/master/docs/android_studio.md')
751 816
752 817
753 if __name__ == '__main__': 818 if __name__ == '__main__':
754 main() 819 main()
OLDNEW
« no previous file with comments | « build/android/gradle/android.jinja ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698