0

Android: Remove apk modules for Android Studio

It is no longer necessary to list all the apk targets as separate
modules now that we have the _all pseudo module. Having the separate
modules resulted in bugs where Android Studio could not distinguish
between prod code and test code since some modules viewed dirs as prod
and some as test. The --split-projects flag can be used to see the
dependency graph, and when only a single module will be generated, the
_all pseudo module will not replace it.

For android studio's _all pseudo module, move all known test dirs to
androidTest instead of main so that they are properly displayed when
filtered.

BUG=620034

Review-Url: https://codereview.chromium.org/2837863002
Cr-Commit-Position: refs/heads/master@{#467704}
This commit is contained in:
wnwen
2017-04-27 09:21:42 -07:00
committed by Commit bot
parent 13d8b0a4a7
commit e851ad4700
3 changed files with 57 additions and 29 deletions

@ -4,7 +4,9 @@
{% macro expand_sourceset(variables, prefix) %}
{% if variables is defined %}
{{ prefix }} {
{% if variables.android_manifest is defined %}
manifest.srcFile "{{ variables.android_manifest }}"
{% endif %}
{% if variables.java_dirs is defined %}
java.srcDirs = [
{% for path in variables.java_dirs %}

@ -199,6 +199,9 @@ class _ProjectEntry(object):
"""Returns the target type from its .build_config."""
return self.DepsInfo()['type']
def IsValid(self):
return self.GetType() in ('android_apk', 'java_library', 'java_binary')
def ResZips(self):
return self.DepsInfo().get('owned_resources_zips', [])
@ -545,6 +548,13 @@ def _GenerateGradleFile(entry, generator, build_vars, source_properties,
_TemplatePath(target_type.split('_')[0]), variables)
def _IsTestDir(path):
return ('javatests/' in path or
'junit/' in path or
'test/' in path or
'testing/' in path)
def _GenerateModuleAll(gradle_output_dir, generator, build_vars,
source_properties, jinja_processor):
"""Returns the data for a pseudo build.gradle of all dirs.
@ -558,12 +568,18 @@ def _GenerateModuleAll(gradle_output_dir, generator, build_vars,
prebuilts = sorted(generator.processed_prebuilts)
def Relativize(paths):
return _RebasePath(paths, os.path.join(gradle_output_dir, _MODULE_ALL))
main_java_dirs = [d for d in java_dirs if not _IsTestDir(d)]
test_java_dirs = [d for d in java_dirs if _IsTestDir(d)]
variables['main'] = {
'android_manifest': Relativize(_DEFAULT_ANDROID_MANIFEST_PATH),
'java_dirs': Relativize(java_dirs),
'java_dirs': Relativize(main_java_dirs),
'prebuilts': Relativize(prebuilts),
'java_excludes': ['**/*.java'],
}
variables['android_test'] = {
'java_dirs': Relativize(test_java_dirs),
'java_excludes': ['**/*.java'],
}
data = jinja_processor.Render(
_TemplatePath(target_type.split('_')[0]), variables)
_WriteFile(
@ -575,7 +591,7 @@ def _GenerateRootGradle(jinja_processor):
return jinja_processor.Render(_TemplatePath('root'))
def _GenerateSettingsGradle(project_entries):
def _GenerateSettingsGradle(project_entries, add_all_module):
"""Returns the data for settings.gradle."""
project_name = os.path.basename(os.path.dirname(host_paths.DIR_SOURCE_ROOT))
lines = []
@ -584,10 +600,11 @@ def _GenerateSettingsGradle(project_entries):
lines.append('rootProject.projectDir = settingsDir')
lines.append('')
lines.append('include ":{0}"'.format(_MODULE_ALL))
lines.append(
'project(":{0}").projectDir = new File(settingsDir, "{0}")'.format(
_MODULE_ALL))
if add_all_module:
lines.append('include ":{0}"'.format(_MODULE_ALL))
lines.append(
'project(":{0}").projectDir = new File(settingsDir, "{0}")'.format(
_MODULE_ALL))
for entry in project_entries:
# Example target: android_webview:android_webview_java__build_config
lines.append('include ":%s"' % entry.ProjectName())
@ -697,7 +714,6 @@ 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.split_projects:
assert not args.use_gradle_process_resources, (
'Gradle resources does not work without --split-projects.')
@ -743,21 +759,22 @@ def main():
if args.split_projects:
main_entries = _FindAllProjectEntries(main_entries)
logging.info('Found %d dependent build_config targets.', len(main_entries))
entries = _CombineTestEntries(main_entries)
entries = [e for e in _CombineTestEntries(main_entries) if e.IsValid()]
logging.info('Creating %d projects for targets.', len(entries))
# When only one entry will be generated we want it to have a valid
# build.gradle file with its own AndroidManifest.
add_all_module = not args.split_projects and len(entries) > 1
logging.warning('Writing .gradle files...')
project_entries = []
zip_tuples = []
generated_inputs = []
for entry in entries:
if entry.GetType() not in ('android_apk', 'java_library', 'java_binary'):
continue
data = _GenerateGradleFile(entry, generator, build_vars, source_properties,
jinja_processor)
if data:
project_entries.append(entry)
# Build all paths references by .gradle that exist within output_dir.
generated_inputs.extend(generator.GeneratedInputs(entry))
zip_tuples.extend(
@ -766,18 +783,21 @@ def main():
zip_tuples.extend(
(s, os.path.join(generator.EntryOutputDir(entry), _RES_SUBDIR))
for s in generator.AllResZips(entry))
_WriteFile(
os.path.join(generator.EntryOutputDir(entry), _GRADLE_BUILD_FILE),
data)
if not add_all_module:
project_entries.append(entry)
_WriteFile(
os.path.join(generator.EntryOutputDir(entry), _GRADLE_BUILD_FILE),
data)
_GenerateModuleAll(_gradle_output_dir, generator, build_vars,
source_properties, jinja_processor)
if add_all_module:
_GenerateModuleAll(_gradle_output_dir, generator, build_vars,
source_properties, jinja_processor)
_WriteFile(os.path.join(generator.project_dir, _GRADLE_BUILD_FILE),
_GenerateRootGradle(jinja_processor))
_WriteFile(os.path.join(generator.project_dir, 'settings.gradle'),
_GenerateSettingsGradle(project_entries))
_GenerateSettingsGradle(project_entries, add_all_module))
sdk_path = _RebasePath(build_vars['android_sdk_root'])
_WriteFile(os.path.join(generator.project_dir, 'local.properties'),
@ -791,7 +811,7 @@ def main():
if zip_tuples:
_ExtractZips(generator.project_dir, zip_tuples)
logging.warning('Project created! (%d subprojects)', len(project_entries))
logging.warning('Project created!')
logging.warning('Generated projects work with Android Studio 2.3')
logging.warning('For more tips: https://chromium.googlesource.com/chromium'
'/src.git/+/master/docs/android_studio.md')

@ -24,12 +24,6 @@ projects for:
build/android/gradle/generate_gradle.py --extra-target //chrome/android:chrome_public_apk
```
For those upgrading from Android Studio 2.2 to 2.3:
* Use `gn clean` and `gn gen`
* Clean up in `//third_party/android_tools` with `git clean -ffd`.
* Remove project from android studio and regenerate with `generate_gradle.py`.
For first-time Android Studio users:
* Avoid running the setup wizard.
@ -37,6 +31,12 @@ For first-time Android Studio users:
`//third_party/android_tools`.
* To skip it, select "Cancel" when it comes up.
For those upgrading from Android Studio 2.2 to 2.3:
* Use `gn clean` and `gn gen`
* Clean up in `//third_party/android_tools` with `git clean -ffd`.
* Remove project from android studio and regenerate with `generate_gradle.py`.
To import the project:
* Use "Import Project", and select the directory containing the generated
@ -52,9 +52,14 @@ You need to re-run `generate_gradle.py` whenever `BUILD.gn` files change.
## How It Works
Android Studio integration works by generating `build.gradle` files based on GN
targets. Each valid target produces a separate Gradle sub-project.
Instrumentation tests are combined with their `apk_under_test`.
By default, only a single module is generated. If more than one apk target is
specified, then an `_all` module is generated. Otherwise a single apk module is
generated. Since instrumentation tests are combined with their `apk_under_test`
target, they count as one module together.
To see more detailed structure of gn targets, the `--split-projects` flag can
be used. This will generate one module for every gn target in the dependency
graph.
### Excluded Files
@ -127,7 +132,7 @@ resources, native libraries, etc.
* Add the line `org.gradle.daemon=true` to `~/.gradle/gradle.properties`,
creating it if necessary.
## Status (as of April 19th, 2017)
## Status (as of April 27th, 2017)
### What works
@ -139,6 +144,7 @@ resources, native libraries, etc.
* Java debugging (see
[here](/docs/android_debugging_instructions.md#Android-Studio)).
* Import resolution and refactoring across all modules.
* Correct lint and AndroidManifest when only one target is specified.
### What doesn't work (yet) ([crbug](https://bugs.chromium.org/p/chromium/issues/detail?id=620034))