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

Unified Diff: build/android/gradle/generate_gradle.py

Issue 2633533002: Android: Instrumentation tests in gradle (Closed)
Patch Set: Fix per review. Created 3 years, 11 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « build/android/gradle/dependencies.jinja ('k') | build/android/gradle/java.jinja » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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')
« no previous file with comments | « build/android/gradle/dependencies.jinja ('k') | build/android/gradle/java.jinja » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698