Android: Android studio single module per target

Existing users can continue to split modules by gn targets by passing
--split-project to generate_gradle.py, although that flag will not
receive the same maintenance going forward, consider it deprecated.

This coalesces java and resource dependencies into the same build.gradle
file for each apk and junit target specified (test apks still get folded
into the apk_under_test target).

Speeds up sync/builds by 10x to 1-3 seconds. Paves the way for using
more of android studio's build steps, since they'll now take 1-3 seconds
rather than 10+ seconds each time.

BUG=620034

Review-Url: https://codereview.chromium.org/2708133002
Cr-Original-Commit-Position: refs/heads/master@{#453257}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: 543908d37bb29cad0925a6553cb6a7261b222133
This commit is contained in:
wnwen 2017-02-27 10:09:29 -08:00 коммит произвёл Commit bot
Родитель b8f5c70b06
Коммит 0952b4961e
2 изменённых файлов: 103 добавлений и 58 удалений

Просмотреть файл

@ -3,16 +3,22 @@
{# found in the LICENSE file. #}
{% macro expand_deps(variables, prefix) %}
{% if variables is defined %}
{% if variables.prebuilts is defined %}
{% for path in variables.prebuilts %}
{{ prefix }} files("{{ path }}")
{% endfor %}
{% endif %}
{% if variables.java_project_deps is defined %}
{% for proj in variables.java_project_deps %}
{{ prefix }} project(":{{ proj }}")
{% endfor %}
{% endif %}
{% if variables.android_project_deps is defined %}
{% for proj in variables.android_project_deps %}
{{ prefix }} project(path: ":{{ proj }}", configuration: "debug")
{% endfor %}
{% endif %}
{% endif %}
{% endmacro %}
dependencies {

Просмотреть файл

@ -197,7 +197,10 @@ class _ProjectEntry(object):
return self.DepsInfo()['type']
def ResZips(self):
return self.DepsInfo().get('owned_resources_zips')
return self.DepsInfo().get('owned_resources_zips', [])
def ResDirs(self):
return self.DepsInfo().get('owned_resources_dirs', [])
def JavaFiles(self):
if self._java_files is None:
@ -213,7 +216,7 @@ class _ProjectEntry(object):
return [p for p in self.JavaFiles() if not p.startswith('..')]
def PrebuiltJars(self):
return self.Gradle()['dependent_prebuilt_jars']
return self.Gradle().get('dependent_prebuilt_jars', [])
def AllEntries(self):
"""Returns a list of all entries that the current entry depends on.
@ -236,36 +239,30 @@ class _ProjectEntry(object):
class _ProjectContextGenerator(object):
"""Helper class to generate gradle build files"""
def __init__(self, project_dir, build_vars, use_gradle_process_resources,
jinja_processor):
jinja_processor, split_projects):
self.project_dir = project_dir
self.build_vars = build_vars
self.use_gradle_process_resources = use_gradle_process_resources
self.jinja_processor = jinja_processor
self.split_projects = split_projects
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 _GenJniLibs(self, root_entry):
libraries = []
for entry in self._GetEntries(root_entry):
libraries += entry.BuildConfig().get('native', [])
if libraries:
return _CreateJniLibsDir(constants.GetOutDirectory(),
self.EntryOutputDir(root_entry), libraries)
return []
def _GenJavaDirs(self, entry):
def _GenJavaDirs(self, root_entry):
java_files = []
for entry in self._GetEntries(root_entry):
java_files += entry.JavaFiles()
java_dirs, excludes = _ComputeJavaSourceDirsAndExcludes(
constants.GetOutDirectory(), entry.JavaFiles())
if self.Srcjars(entry):
java_dirs.append(
os.path.join(self.EntryOutputDir(entry), _SRCJARS_SUBDIR))
constants.GetOutDirectory(), java_files)
return java_dirs, excludes
def _GenResDirs(self, entry):
res_dirs = list(entry.DepsInfo().get('owned_resources_dirs', []))
if entry.ResZips():
res_dirs.append(os.path.join(self.EntryOutputDir(entry), _RES_SUBDIR))
return res_dirs
def _GenCustomManifest(self, entry):
"""Returns the path to the generated AndroidManifest.xml.
@ -297,43 +294,75 @@ class _ProjectContextGenerator(object):
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):
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(_RebasePath(entry.ResZips()))
generated_inputs.extend(entry.GeneratedJavaFiles())
generated_inputs.extend(entry.PrebuiltJars())
return generated_inputs
def _GetEntries(self, entry):
if self.split_projects:
return [entry]
return entry.AllEntries()
def Generate(self, entry):
variables = {}
java_dirs, excludes = self._GenJavaDirs(entry)
variables['java_dirs'] = self._Relativize(entry, java_dirs)
variables['java_excludes'] = excludes
variables['jni_libs'] = self._Relativize(entry, self._GenJniLibs(entry))
variables['res_dirs'] = self._Relativize(entry, self._GenResDirs(entry))
android_manifest = entry.Gradle().get('android_manifest')
if not android_manifest:
android_manifest = self._GenCustomManifest(entry)
variables['android_manifest'] = self._Relativize(entry, android_manifest)
def EntryOutputDir(self, entry):
return os.path.join(self.project_dir, entry.GradleSubdir())
def AllSrcjars(self, root_entry):
srcjars = []
for entry in self._GetEntries(root_entry):
srcjars += self._Srcjars(entry)
return set(srcjars)
def AllResZips(self, root_entry):
res_zips = []
for entry in self._GetEntries(root_entry):
res_zips += entry.ResZips()
return set(_RebasePath(res_zips))
def GeneratedInputs(self, root_entry):
generated_inputs = set(self.AllResZips(root_entry))
generated_inputs.update(self.AllSrcjars(root_entry))
for entry in self._GetEntries(root_entry):
generated_inputs.update(entry.GeneratedJavaFiles())
generated_inputs.update(entry.PrebuiltJars())
return set(generated_inputs)
def Generate(self, root_entry):
# TODO(agrieve): Add an option to use interface jars and see if that speeds
# things up at all.
variables['prebuilts'] = self._Relativize(entry, entry.PrebuiltJars())
deps = [_ProjectEntry.FromBuildConfigPath(p)
for p in entry.Gradle()['dependent_android_projects']]
variables['android_project_deps'] = [d.ProjectName() for d in deps]
deps = [_ProjectEntry.FromBuildConfigPath(p)
for p in entry.Gradle()['dependent_java_projects']]
variables['java_project_deps'] = [d.ProjectName() for d in deps]
variables = {}
java_dirs, excludes = self._GenJavaDirs(root_entry)
java_dirs.sort()
variables['java_dirs'] = self._Relativize(root_entry, java_dirs)
variables['java_dirs'].append(_SRCJARS_SUBDIR)
variables['java_excludes'] = excludes
variables['jni_libs'] = self._Relativize(
root_entry, set(self._GenJniLibs(root_entry)))
variables['prebuilts'] = [
p for e in self._GetEntries(root_entry) for p in e.PrebuiltJars()]
variables['res_dirs'] = [
p for e in self._GetEntries(root_entry) for p in e.ResDirs()]
for entry in self._GetEntries(root_entry):
variables['prebuilts'] += entry.PrebuiltJars()
variables['res_dirs'] += entry.ResDirs()
variables['prebuilts'] = self._Relativize(
root_entry, set(variables['prebuilts']))
variables['res_dirs'] = self._Relativize(
root_entry, set(variables['res_dirs']))
variables['res_dirs'].append(_RES_SUBDIR)
android_manifest = root_entry.Gradle().get('android_manifest')
if not android_manifest:
android_manifest = self._GenCustomManifest(root_entry)
variables['android_manifest'] = self._Relativize(
root_entry, android_manifest)
if self.split_projects:
deps = [_ProjectEntry.FromBuildConfigPath(p)
for p in root_entry.Gradle()['dependent_android_projects']]
variables['android_project_deps'] = [d.ProjectName() for d in deps]
deps = [_ProjectEntry.FromBuildConfigPath(p)
for p in root_entry.Gradle()['dependent_java_projects']]
variables['java_project_deps'] = [d.ProjectName() for d in deps]
return variables
@ -611,6 +640,10 @@ def main():
parser.add_argument('--use-gradle-process-resources',
action='store_true',
help='Have gradle generate R.java rather than ninja')
parser.add_argument('--split-projects',
action='store_true',
help='Split projects by their gn deps rather than '
'combining all the dependencies of each target')
args = parser.parse_args()
if args.output_directory:
constants.SetOutputDirectory(args.output_directory)
@ -619,12 +652,17 @@ def main():
devil_chromium.Initialize(output_directory=output_dir)
run_tests_helper.SetLogLevel(args.verbose_count)
# TODO(wnwen): Fix packaging so that gradle resources work in this case.
if args.use_gradle_process_resources:
assert args.split_projects, (
'Gradle resources does not yet work without --split-projects.')
_gradle_output_dir = os.path.abspath(
args.project_dir.replace('$CHROMIUM_OUTPUT_DIR', output_dir))
jinja_processor = jinja_template.JinjaProcessor(_FILE_DIR)
build_vars = _ReadBuildVars(output_dir)
generator = _ProjectContextGenerator(_gradle_output_dir, build_vars,
args.use_gradle_process_resources, jinja_processor)
args.use_gradle_process_resources, jinja_processor, args.split_projects)
logging.warning('Creating project at: %s', generator.project_dir)
if args.all:
@ -649,9 +687,10 @@ def main():
if args.all:
main_entries = [e for e in main_entries if e.GetType() == 'android_apk']
all_entries = _FindAllProjectEntries(main_entries)
logging.info('Found %d dependent build_config targets.', len(all_entries))
entries = _CombineTestEntries(all_entries)
if args.split_projects:
main_entries = _FindAllProjectEntries(main_entries)
logging.info('Found %d dependent build_config targets.', len(main_entries))
entries = _CombineTestEntries(main_entries)
logging.info('Creating %d projects for targets.', len(entries))
logging.warning('Writing .gradle files...')
@ -669,10 +708,10 @@ def main():
generated_inputs.extend(generator.GeneratedInputs(entry))
zip_tuples.extend(
(s, os.path.join(generator.EntryOutputDir(entry), _SRCJARS_SUBDIR))
for s in generator.Srcjars(entry))
for s in generator.AllSrcjars(entry))
zip_tuples.extend(
(s, os.path.join(generator.EntryOutputDir(entry), _RES_SUBDIR))
for s in _RebasePath(entry.ResZips()))
for s in generator.AllResZips(entry))
_WriteFile(
os.path.join(generator.EntryOutputDir(entry), 'build.gradle'), data)