| Index: build/android/gradle/generate_gradle.py
|
| diff --git a/build/android/gradle/generate_gradle.py b/build/android/gradle/generate_gradle.py
|
| index 3c08114cfe43ddddd14f35c4908cab32690f1953..268650061d8d78952d66670924c07554fe9d5d62 100755
|
| --- a/build/android/gradle/generate_gradle.py
|
| +++ b/build/android/gradle/generate_gradle.py
|
| @@ -115,13 +115,15 @@ def _QueryForAllGnTargets(output_dir):
|
|
|
|
|
| class _ProjectEntry(object):
|
| - """Helper class for various path transformations."""
|
| + """Helper class for project entries."""
|
| def __init__(self, gn_target):
|
| assert gn_target.startswith('//'), gn_target
|
| if ':' not in gn_target:
|
| gn_target = '%s:%s' % (gn_target, os.path.basename(gn_target))
|
| self._gn_target = gn_target
|
| self._build_config = None
|
| + self._java_files = None
|
| + self.android_test_entry = None
|
|
|
| @classmethod
|
| def FromBuildConfigPath(cls, path):
|
| @@ -164,9 +166,91 @@ class _ProjectEntry(object):
|
| self._build_config = build_utils.ReadJson(_RebasePath(path))
|
| return self._build_config
|
|
|
| + def DepsInfo(self):
|
| + return self.BuildConfig()['deps_info']
|
| +
|
| + def Gradle(self):
|
| + return self.BuildConfig()['gradle']
|
| +
|
| def GetType(self):
|
| """Returns the target type from its .build_config."""
|
| - return self.BuildConfig()['deps_info']['type']
|
| + return self.DepsInfo()['type']
|
| +
|
| + def JavaFiles(self):
|
| + if self._java_files is None:
|
| + java_sources_file = self.Gradle().get('java_sources_file')
|
| + java_files = []
|
| + if java_sources_file:
|
| + java_sources_file = _RebasePath(java_sources_file)
|
| + java_files = build_utils.ReadSourcesList(java_sources_file)
|
| + self._java_files = java_files
|
| + return self._java_files
|
| +
|
| +
|
| +class _ProjectContextGenerator(object):
|
| + """Helper class to generate gradle build files"""
|
| + def __init__(self, project_dir, use_gradle_process_resources):
|
| + self.project_dir = project_dir
|
| + self.use_gradle_process_resources = use_gradle_process_resources
|
| +
|
| + def _GenJniLibs(self, entry):
|
| + native_section = entry.BuildConfig().get('native')
|
| + if native_section:
|
| + jni_libs = _CreateJniLibsDir(
|
| + constants.GetOutDirectory(), self.EntryOutputDir(entry),
|
| + native_section.get('libraries'))
|
| + else:
|
| + jni_libs = []
|
| + return jni_libs
|
| +
|
| + def _GenJavaDirs(self, entry):
|
| + java_dirs = _CreateJavaSourceDir(
|
| + constants.GetOutDirectory(), self.EntryOutputDir(entry),
|
| + entry.JavaFiles())
|
| + if self.Srcjars(entry):
|
| + java_dirs.append(
|
| + os.path.join(self.EntryOutputDir(entry), _SRCJARS_SUBDIR))
|
| + return java_dirs
|
| +
|
| + def _Relativize(self, entry, paths):
|
| + return _RebasePath(paths, self.EntryOutputDir(entry))
|
| +
|
| + def EntryOutputDir(self, entry):
|
| + return os.path.join(self.project_dir, entry.GradleSubdir())
|
| +
|
| + def Srcjars(self, entry):
|
| + srcjars = _RebasePath(entry.Gradle().get('bundled_srcjars', []))
|
| + if not self.use_gradle_process_resources:
|
| + srcjars += _RebasePath(entry.BuildConfig()['javac']['srcjars'])
|
| + return srcjars
|
| +
|
| + def GeneratedInputs(self, entry):
|
| + generated_inputs = []
|
| + generated_inputs.extend(self.Srcjars(entry))
|
| + generated_inputs.extend(
|
| + p for p in entry.JavaFiles() if not p.startswith('..'))
|
| + generated_inputs.extend(entry.Gradle()['dependent_prebuilt_jars'])
|
| + return generated_inputs
|
| +
|
| + def Generate(self, entry):
|
| + variables = {}
|
| + android_test_manifest = entry.Gradle().get(
|
| + 'android_manifest', _DEFAULT_ANDROID_MANIFEST_PATH)
|
| + variables['android_manifest'] = self._Relativize(
|
| + entry, android_test_manifest)
|
| + variables['java_dirs'] = self._Relativize(entry, self._GenJavaDirs(entry))
|
| + variables['jni_libs'] = self._Relativize(entry, self._GenJniLibs(entry))
|
| + deps = [_ProjectEntry.FromBuildConfigPath(p)
|
| + for p in entry.Gradle()['dependent_android_projects']]
|
| + variables['android_project_deps'] = [d.ProjectName() for d in deps]
|
| + # TODO(agrieve): Add an option to use interface jars and see if that speeds
|
| + # things up at all.
|
| + variables['prebuilts'] = self._Relativize(
|
| + entry, entry.Gradle()['dependent_prebuilt_jars'])
|
| + deps = [_ProjectEntry.FromBuildConfigPath(p)
|
| + for p in entry.Gradle()['dependent_java_projects']]
|
| + variables['java_project_deps'] = [d.ProjectName() for d in deps]
|
| + return variables
|
|
|
|
|
| def _ComputeJavaSourceDirs(java_files):
|
| @@ -278,12 +362,10 @@ def _GenerateLocalProperties(sdk_dir):
|
| ''])
|
|
|
|
|
| -def _GenerateGradleFile(build_config, build_vars, java_dirs, jni_libs,
|
| - relativize, use_gradle_process_resources,
|
| - jinja_processor):
|
| +def _GenerateGradleFile(entry, generator, build_vars, jinja_processor):
|
| """Returns the data for a project's build.gradle."""
|
| - deps_info = build_config['deps_info']
|
| - gradle = build_config['gradle']
|
| + deps_info = entry.DepsInfo()
|
| + gradle = entry.Gradle()
|
|
|
| variables = {
|
| 'sourceSetName': 'main',
|
| @@ -294,8 +376,7 @@ def _GenerateGradleFile(build_config, build_vars, java_dirs, jni_libs,
|
| elif deps_info['type'] == 'java_library':
|
| if deps_info['is_prebuilt'] or deps_info['gradle_treat_as_prebuilt']:
|
| return None
|
| -
|
| - if deps_info['requires_android']:
|
| + elif deps_info['requires_android']:
|
| target_type = 'android_library'
|
| else:
|
| target_type = 'java_library'
|
| @@ -312,25 +393,15 @@ def _GenerateGradleFile(build_config, build_vars, java_dirs, jni_libs,
|
|
|
| variables['target_name'] = os.path.splitext(deps_info['name'])[0]
|
| variables['template_type'] = target_type
|
| - variables['use_gradle_process_resources'] = use_gradle_process_resources
|
| + variables['use_gradle_process_resources'] = (
|
| + generator.use_gradle_process_resources)
|
| variables['build_tools_version'] = (
|
| build_vars['android_sdk_build_tools_version'])
|
| variables['compile_sdk_version'] = build_vars['android_sdk_version']
|
| - android_manifest = gradle.get('android_manifest',
|
| - _DEFAULT_ANDROID_MANIFEST_PATH)
|
| - variables['android_manifest'] = relativize(android_manifest)
|
| - variables['java_dirs'] = relativize(java_dirs)
|
| - variables['jni_libs'] = relativize(jni_libs)
|
| - # TODO(agrieve): Add an option to use interface jars and see if that speeds
|
| - # things up at all.
|
| - variables['prebuilts'] = relativize(gradle['dependent_prebuilt_jars'])
|
| - deps = [_ProjectEntry.FromBuildConfigPath(p)
|
| - for p in gradle['dependent_android_projects']]
|
| -
|
| - variables['android_project_deps'] = [d.ProjectName() for d in deps]
|
| - deps = [_ProjectEntry.FromBuildConfigPath(p)
|
| - for p in gradle['dependent_java_projects']]
|
| - variables['java_project_deps'] = [d.ProjectName() for d in deps]
|
| + variables['main'] = generator.Generate(entry)
|
| + if entry.android_test_entry:
|
| + variables['android_test'] = generator.Generate(
|
| + entry.android_test_entry)
|
|
|
| return jinja_processor.Render(
|
| _TemplatePath(target_type.split('_')[0]), variables)
|
| @@ -380,16 +451,44 @@ def _FindAllProjectEntries(main_entries):
|
| if cur_entry in found:
|
| continue
|
| found.add(cur_entry)
|
| - build_config = cur_entry.BuildConfig()
|
| - sub_config_paths = build_config['deps_info']['deps_configs']
|
| + sub_config_paths = cur_entry.DepsInfo()['deps_configs']
|
| to_scan.extend(
|
| _ProjectEntry.FromBuildConfigPath(p) for p in sub_config_paths)
|
| return list(found)
|
|
|
|
|
| +def _CombineTestEntries(entries):
|
| + """Combines test apks into the androidTest source set of their target.
|
| +
|
| + - Speeds up android studio
|
| + - Adds proper dependency between test and apk_under_test
|
| + - Doesn't work for junit yet due to resulting circular dependencies
|
| + - e.g. base_junit_tests > base_junit_test_support > base_java
|
| + """
|
| + combined_entries = []
|
| + android_test_entries = {}
|
| + for entry in entries:
|
| + target_name = entry.GnTarget()
|
| + if (target_name.endswith('_test_apk__apk') and
|
| + 'apk_under_test' in entry.Gradle()):
|
| + apk_name = entry.Gradle()['apk_under_test']
|
| + android_test_entries[apk_name] = entry
|
| + else:
|
| + combined_entries.append(entry)
|
| + for entry in combined_entries:
|
| + target_name = entry.DepsInfo()['name']
|
| + if target_name in android_test_entries:
|
| + entry.android_test_entry = android_test_entries[target_name]
|
| + del android_test_entries[target_name]
|
| + # Add unmatched test entries as individual targets.
|
| + combined_entries.extend(android_test_entries.values())
|
| + return combined_entries
|
| +
|
| +
|
| def main():
|
| parser = argparse.ArgumentParser()
|
| parser.add_argument('--output-directory',
|
| + default='out/Debug',
|
| help='Path to the root build directory.')
|
| parser.add_argument('-v',
|
| '--verbose',
|
| @@ -419,20 +518,21 @@ def main():
|
| devil_chromium.Initialize(output_directory=output_dir)
|
| run_tests_helper.SetLogLevel(args.verbose_count)
|
|
|
| - gradle_output_dir = os.path.abspath(
|
| + _gradle_output_dir = os.path.abspath(
|
| args.project_dir.replace('$CHROMIUM_OUTPUT_DIR', output_dir))
|
| - logging.warning('Creating project at: %s', gradle_output_dir)
|
| + generator = _ProjectContextGenerator(
|
| + _gradle_output_dir, args.use_gradle_process_resources)
|
| + logging.warning('Creating project at: %s', generator.project_dir)
|
|
|
| if args.all:
|
| # Run GN gen if necessary (faster than running "gn gen" in the no-op case).
|
| - _RunNinja(output_dir, ['build.ninja'])
|
| + _RunNinja(constants.GetOutDirectory(), ['build.ninja'])
|
| # Query ninja for all __build_config targets.
|
| targets = _QueryForAllGnTargets(output_dir)
|
| else:
|
| targets = args.targets or _DEFAULT_TARGETS
|
| - # TODO(agrieve): See if it makes sense to utilize Gradle's test constructs
|
| - # for our instrumentation tests.
|
| targets = [re.sub(r'_test_apk$', '_test_apk__apk', t) for t in targets]
|
| + # TODO(wnwen): Utilize Gradle's test constructs for our junit tests?
|
| targets = [re.sub(r'_junit_tests$', '_junit_tests__java_binary', t)
|
| for t in targets]
|
|
|
| @@ -448,6 +548,8 @@ def main():
|
|
|
| all_entries = _FindAllProjectEntries(main_entries)
|
| logging.info('Found %d dependent build_config targets.', len(all_entries))
|
| + entries = _CombineTestEntries(all_entries)
|
| + logging.info('Creating %d projects for targets.', len(entries))
|
|
|
| logging.warning('Writing .gradle files...')
|
| jinja_processor = jinja_template.JinjaProcessor(_FILE_DIR)
|
| @@ -455,57 +557,29 @@ def main():
|
| project_entries = []
|
| srcjar_tuples = []
|
| generated_inputs = []
|
| - for entry in all_entries:
|
| + for entry in entries:
|
| if entry.GetType() not in ('android_apk', 'java_library', 'java_binary'):
|
| continue
|
|
|
| - entry_output_dir = os.path.join(gradle_output_dir, entry.GradleSubdir())
|
| - relativize = lambda x, d=entry_output_dir: _RebasePath(x, d)
|
| - build_config = entry.BuildConfig()
|
| -
|
| - srcjars = _RebasePath(build_config['gradle'].get('bundled_srcjars', []))
|
| - if not args.use_gradle_process_resources:
|
| - srcjars += _RebasePath(build_config['javac']['srcjars'])
|
| -
|
| - java_sources_file = build_config['gradle'].get('java_sources_file')
|
| - java_files = []
|
| - if java_sources_file:
|
| - java_sources_file = _RebasePath(java_sources_file)
|
| - java_files = build_utils.ReadSourcesList(java_sources_file)
|
| -
|
| - java_dirs = _CreateJavaSourceDir(output_dir, entry_output_dir, java_files)
|
| - if srcjars:
|
| - java_dirs.append(os.path.join(entry_output_dir, _SRCJARS_SUBDIR))
|
| -
|
| - native_section = build_config.get('native')
|
| - if native_section:
|
| - jni_libs = _CreateJniLibsDir(
|
| - output_dir, entry_output_dir, native_section.get('libraries'))
|
| - else:
|
| - jni_libs = []
|
| -
|
| - data = _GenerateGradleFile(build_config, build_vars, java_dirs, jni_libs,
|
| - relativize, args.use_gradle_process_resources,
|
| - jinja_processor)
|
| + data = _GenerateGradleFile(entry, generator, build_vars, jinja_processor)
|
| if data:
|
| project_entries.append(entry)
|
| # Build all paths references by .gradle that exist within output_dir.
|
| - generated_inputs.extend(srcjars)
|
| - generated_inputs.extend(p for p in java_files if not p.startswith('..'))
|
| - generated_inputs.extend(build_config['gradle']['dependent_prebuilt_jars'])
|
| -
|
| + generated_inputs.extend(generator.GeneratedInputs(entry))
|
| srcjar_tuples.extend(
|
| - (s, os.path.join(entry_output_dir, _SRCJARS_SUBDIR)) for s in srcjars)
|
| - _WriteFile(os.path.join(entry_output_dir, 'build.gradle'), data)
|
| + (s, os.path.join(generator.EntryOutputDir(entry), _SRCJARS_SUBDIR))
|
| + for s in generator.Srcjars(entry))
|
| + _WriteFile(
|
| + os.path.join(generator.EntryOutputDir(entry), 'build.gradle'), data)
|
|
|
| - _WriteFile(os.path.join(gradle_output_dir, 'build.gradle'),
|
| + _WriteFile(os.path.join(generator.project_dir, 'build.gradle'),
|
| _GenerateRootGradle(jinja_processor))
|
|
|
| - _WriteFile(os.path.join(gradle_output_dir, 'settings.gradle'),
|
| + _WriteFile(os.path.join(generator.project_dir, 'settings.gradle'),
|
| _GenerateSettingsGradle(project_entries))
|
|
|
| sdk_path = _RebasePath(build_vars['android_sdk_root'])
|
| - _WriteFile(os.path.join(gradle_output_dir, 'local.properties'),
|
| + _WriteFile(os.path.join(generator.project_dir, 'local.properties'),
|
| _GenerateLocalProperties(sdk_path))
|
|
|
| if generated_inputs:
|
| @@ -514,7 +588,7 @@ def main():
|
| _RunNinja(output_dir, targets)
|
|
|
| if srcjar_tuples:
|
| - _ExtractSrcjars(gradle_output_dir, srcjar_tuples)
|
| + _ExtractSrcjars(generator.project_dir, srcjar_tuples)
|
|
|
| logging.warning('Project created! (%d subprojects)', len(project_entries))
|
| logging.warning('Generated projects work best with Android Studio 2.2')
|
|
|