Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 168 path = os.path.join('gen', self.GradleSubdir() + '.build_config') | 168 path = os.path.join('gen', self.GradleSubdir() + '.build_config') |
| 169 self._build_config = build_utils.ReadJson(_RebasePath(path)) | 169 self._build_config = build_utils.ReadJson(_RebasePath(path)) |
| 170 return self._build_config | 170 return self._build_config |
| 171 | 171 |
| 172 def DepsInfo(self): | 172 def DepsInfo(self): |
| 173 return self.BuildConfig()['deps_info'] | 173 return self.BuildConfig()['deps_info'] |
| 174 | 174 |
| 175 def Gradle(self): | 175 def Gradle(self): |
| 176 return self.BuildConfig()['gradle'] | 176 return self.BuildConfig()['gradle'] |
| 177 | 177 |
| 178 def Javac(self): | |
| 179 return self.BuildConfig()['javac'] | |
| 180 | |
| 178 def GetType(self): | 181 def GetType(self): |
| 179 """Returns the target type from its .build_config.""" | 182 """Returns the target type from its .build_config.""" |
| 180 return self.DepsInfo()['type'] | 183 return self.DepsInfo()['type'] |
| 181 | 184 |
| 182 def ResZips(self): | 185 def ResZips(self): |
| 183 return self.DepsInfo().get('owned_resources_zips') | 186 return self.DepsInfo().get('owned_resources_zips') |
| 184 | 187 |
| 185 def JavaFiles(self): | 188 def JavaFiles(self): |
| 186 if self._java_files is None: | 189 if self._java_files is None: |
| 187 java_sources_file = self.Gradle().get('java_sources_file') | 190 java_sources_file = self.Gradle().get('java_sources_file') |
| 188 java_files = [] | 191 java_files = [] |
| 189 if java_sources_file: | 192 if java_sources_file: |
| 190 java_sources_file = _RebasePath(java_sources_file) | 193 java_sources_file = _RebasePath(java_sources_file) |
| 191 java_files = build_utils.ReadSourcesList(java_sources_file) | 194 java_files = build_utils.ReadSourcesList(java_sources_file) |
| 192 self._java_files = java_files | 195 self._java_files = java_files |
| 193 return self._java_files | 196 return self._java_files |
| 194 | 197 |
| 195 | 198 |
| 196 class _ProjectContextGenerator(object): | 199 class _ProjectContextGenerator(object): |
| 197 """Helper class to generate gradle build files""" | 200 """Helper class to generate gradle build files""" |
| 198 def __init__(self, project_dir, use_gradle_process_resources): | 201 def __init__( |
| 202 self, project_dir, use_gradle_process_resources, jinja_processor): | |
| 199 self.project_dir = project_dir | 203 self.project_dir = project_dir |
| 200 self.use_gradle_process_resources = use_gradle_process_resources | 204 self.use_gradle_process_resources = use_gradle_process_resources |
| 205 self.jinja_processor = jinja_processor | |
| 201 | 206 |
| 202 def _GenJniLibs(self, entry): | 207 def _GenJniLibs(self, entry): |
| 203 native_section = entry.BuildConfig().get('native') | 208 native_section = entry.BuildConfig().get('native') |
| 204 if native_section: | 209 if native_section: |
| 205 jni_libs = _CreateJniLibsDir( | 210 jni_libs = _CreateJniLibsDir( |
| 206 constants.GetOutDirectory(), self.EntryOutputDir(entry), | 211 constants.GetOutDirectory(), self.EntryOutputDir(entry), |
| 207 native_section.get('libraries')) | 212 native_section.get('libraries')) |
| 208 else: | 213 else: |
| 209 jni_libs = [] | 214 jni_libs = [] |
| 210 return jni_libs | 215 return jni_libs |
| 211 | 216 |
| 212 def _GenJavaDirs(self, entry): | 217 def _GenJavaDirs(self, entry): |
| 213 java_dirs, excludes = _CreateJavaSourceDir( | 218 java_dirs, excludes = _CreateJavaSourceDir( |
| 214 constants.GetOutDirectory(), entry.JavaFiles()) | 219 constants.GetOutDirectory(), entry.JavaFiles()) |
| 215 if self.Srcjars(entry): | 220 if self.Srcjars(entry): |
| 216 java_dirs.append( | 221 java_dirs.append( |
| 217 os.path.join(self.EntryOutputDir(entry), _SRCJARS_SUBDIR)) | 222 os.path.join(self.EntryOutputDir(entry), _SRCJARS_SUBDIR)) |
| 218 return java_dirs, excludes | 223 return java_dirs, excludes |
| 219 | 224 |
| 220 def _GenResDirs(self, entry): | 225 def _GenResDirs(self, entry): |
| 221 res_dirs = list(entry.DepsInfo().get('owned_resources_dirs', [])) | 226 res_dirs = list(entry.DepsInfo().get('owned_resources_dirs', [])) |
| 222 if entry.ResZips(): | 227 if entry.ResZips(): |
| 223 res_dirs.append(os.path.join(self.EntryOutputDir(entry), _RES_SUBDIR)) | 228 res_dirs.append(os.path.join(self.EntryOutputDir(entry), _RES_SUBDIR)) |
| 224 return res_dirs | 229 return res_dirs |
| 225 | 230 |
| 231 def _GenCustomManifest(self, entry): | |
| 232 """Returns the path to the generated AndroidManifest.xml.""" | |
| 233 javac = entry.Javac() | |
| 234 resource_packages = javac['resource_packages'] | |
| 235 output_file = os.path.join( | |
| 236 self.EntryOutputDir(entry), 'AndroidManifest.xml') | |
| 237 | |
| 238 if not resource_packages: | |
| 239 logging.error('Target ' + entry.GnTarget() + ' includes resources from ' | |
| 240 'unknown package. Unable to process with gradle.') | |
| 241 return _DEFAULT_ANDROID_MANIFEST_PATH | |
| 242 elif len(resource_packages) > 1: | |
| 243 logging.error('Target ' + entry.GnTarget() + ' includes resources from ' | |
| 244 'multiple packages. Unable to process with gradle.') | |
| 245 return _DEFAULT_ANDROID_MANIFEST_PATH | |
| 246 | |
| 247 variables = {} | |
| 248 variables['package'] = resource_packages[0] | |
| 249 | |
| 250 data = self.jinja_processor.Render(_TemplatePath('manifest'), variables) | |
| 251 _WriteFile(output_file, data) | |
| 252 | |
| 253 return output_file | |
| 254 | |
| 226 def _Relativize(self, entry, paths): | 255 def _Relativize(self, entry, paths): |
| 227 return _RebasePath(paths, self.EntryOutputDir(entry)) | 256 return _RebasePath(paths, self.EntryOutputDir(entry)) |
| 228 | 257 |
| 229 def EntryOutputDir(self, entry): | 258 def EntryOutputDir(self, entry): |
| 230 return os.path.join(self.project_dir, entry.GradleSubdir()) | 259 return os.path.join(self.project_dir, entry.GradleSubdir()) |
| 231 | 260 |
| 232 def Srcjars(self, entry): | 261 def Srcjars(self, entry): |
| 233 srcjars = _RebasePath(entry.Gradle().get('bundled_srcjars', [])) | 262 srcjars = _RebasePath(entry.Gradle().get('bundled_srcjars', [])) |
| 234 if not self.use_gradle_process_resources: | 263 if not self.use_gradle_process_resources: |
| 235 srcjars += _RebasePath(entry.BuildConfig()['javac']['srcjars']) | 264 srcjars += _RebasePath(entry.BuildConfig()['javac']['srcjars']) |
| 236 return srcjars | 265 return srcjars |
| 237 | 266 |
| 238 def GeneratedInputs(self, entry): | 267 def GeneratedInputs(self, entry): |
| 239 generated_inputs = [] | 268 generated_inputs = [] |
| 240 generated_inputs.extend(self.Srcjars(entry)) | 269 generated_inputs.extend(self.Srcjars(entry)) |
| 241 generated_inputs.extend(_RebasePath(entry.ResZips())) | 270 generated_inputs.extend(_RebasePath(entry.ResZips())) |
| 242 generated_inputs.extend( | 271 generated_inputs.extend( |
| 243 p for p in entry.JavaFiles() if not p.startswith('..')) | 272 p for p in entry.JavaFiles() if not p.startswith('..')) |
| 244 generated_inputs.extend(entry.Gradle()['dependent_prebuilt_jars']) | 273 generated_inputs.extend(entry.Gradle()['dependent_prebuilt_jars']) |
| 245 return generated_inputs | 274 return generated_inputs |
| 246 | 275 |
| 247 def Generate(self, entry): | 276 def Generate(self, entry): |
| 248 variables = {} | 277 variables = {} |
| 249 android_test_manifest = entry.Gradle().get( | |
| 250 'android_manifest', _DEFAULT_ANDROID_MANIFEST_PATH) | |
| 251 variables['android_manifest'] = self._Relativize( | |
| 252 entry, android_test_manifest) | |
| 253 java_dirs, excludes = self._GenJavaDirs(entry) | 278 java_dirs, excludes = self._GenJavaDirs(entry) |
| 254 variables['java_dirs'] = self._Relativize(entry, java_dirs) | 279 variables['java_dirs'] = self._Relativize(entry, java_dirs) |
| 255 variables['java_excludes'] = excludes | 280 variables['java_excludes'] = excludes |
| 256 variables['jni_libs'] = self._Relativize(entry, self._GenJniLibs(entry)) | 281 variables['jni_libs'] = self._Relativize(entry, self._GenJniLibs(entry)) |
| 257 variables['res_dirs'] = self._Relativize(entry, self._GenResDirs(entry)) | 282 variables['res_dirs'] = self._Relativize(entry, self._GenResDirs(entry)) |
| 283 android_manifest = entry.Gradle().get('android_manifest') | |
| 284 if not android_manifest: | |
| 285 # Gradle uses package id from manifest when generating R.class. So, we | |
| 286 # need to generate a custom manifest if we let gradle process resources. | |
|
agrieve
2017/02/16 15:28:01
nit: can you add a note that applicationId doesn't
sakal-chromium
2017/02/16 15:47:37
Done.
| |
| 287 if self.use_gradle_process_resources and variables['res_dirs']: | |
|
agrieve
2017/02/16 15:28:01
nit: I think we'll want to do this regardless of u
sakal-chromium
2017/02/16 15:47:37
Done.
| |
| 288 android_manifest = self._GenCustomManifest(entry) | |
| 289 else: | |
| 290 android_manifest = _DEFAULT_ANDROID_MANIFEST_PATH | |
| 291 variables['android_manifest'] = self._Relativize(entry, android_manifest) | |
| 258 deps = [_ProjectEntry.FromBuildConfigPath(p) | 292 deps = [_ProjectEntry.FromBuildConfigPath(p) |
| 259 for p in entry.Gradle()['dependent_android_projects']] | 293 for p in entry.Gradle()['dependent_android_projects']] |
| 260 variables['android_project_deps'] = [d.ProjectName() for d in deps] | 294 variables['android_project_deps'] = [d.ProjectName() for d in deps] |
| 261 # TODO(agrieve): Add an option to use interface jars and see if that speeds | 295 # TODO(agrieve): Add an option to use interface jars and see if that speeds |
| 262 # things up at all. | 296 # things up at all. |
| 263 variables['prebuilts'] = self._Relativize( | 297 variables['prebuilts'] = self._Relativize( |
| 264 entry, entry.Gradle()['dependent_prebuilt_jars']) | 298 entry, entry.Gradle()['dependent_prebuilt_jars']) |
| 265 deps = [_ProjectEntry.FromBuildConfigPath(p) | 299 deps = [_ProjectEntry.FromBuildConfigPath(p) |
| 266 for p in entry.Gradle()['dependent_java_projects']] | 300 for p in entry.Gradle()['dependent_java_projects']] |
| 267 variables['java_project_deps'] = [d.ProjectName() for d in deps] | 301 variables['java_project_deps'] = [d.ProjectName() for d in deps] |
| (...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 537 args = parser.parse_args() | 571 args = parser.parse_args() |
| 538 if args.output_directory: | 572 if args.output_directory: |
| 539 constants.SetOutputDirectory(args.output_directory) | 573 constants.SetOutputDirectory(args.output_directory) |
| 540 constants.CheckOutputDirectory() | 574 constants.CheckOutputDirectory() |
| 541 output_dir = constants.GetOutDirectory() | 575 output_dir = constants.GetOutDirectory() |
| 542 devil_chromium.Initialize(output_directory=output_dir) | 576 devil_chromium.Initialize(output_directory=output_dir) |
| 543 run_tests_helper.SetLogLevel(args.verbose_count) | 577 run_tests_helper.SetLogLevel(args.verbose_count) |
| 544 | 578 |
| 545 _gradle_output_dir = os.path.abspath( | 579 _gradle_output_dir = os.path.abspath( |
| 546 args.project_dir.replace('$CHROMIUM_OUTPUT_DIR', output_dir)) | 580 args.project_dir.replace('$CHROMIUM_OUTPUT_DIR', output_dir)) |
| 581 jinja_processor = jinja_template.JinjaProcessor(_FILE_DIR) | |
| 547 generator = _ProjectContextGenerator( | 582 generator = _ProjectContextGenerator( |
| 548 _gradle_output_dir, args.use_gradle_process_resources) | 583 _gradle_output_dir, args.use_gradle_process_resources, jinja_processor) |
| 549 logging.warning('Creating project at: %s', generator.project_dir) | 584 logging.warning('Creating project at: %s', generator.project_dir) |
| 550 | 585 |
| 551 if args.all: | 586 if args.all: |
| 552 # Run GN gen if necessary (faster than running "gn gen" in the no-op case). | 587 # Run GN gen if necessary (faster than running "gn gen" in the no-op case). |
| 553 _RunNinja(constants.GetOutDirectory(), ['build.ninja']) | 588 _RunNinja(constants.GetOutDirectory(), ['build.ninja']) |
| 554 # Query ninja for all __build_config targets. | 589 # Query ninja for all __build_config targets. |
| 555 targets = _QueryForAllGnTargets(output_dir) | 590 targets = _QueryForAllGnTargets(output_dir) |
| 556 else: | 591 else: |
| 557 targets = args.targets or _DEFAULT_TARGETS | 592 targets = args.targets or _DEFAULT_TARGETS |
| 558 targets = [re.sub(r'_test_apk$', '_test_apk__apk', t) for t in targets] | 593 targets = [re.sub(r'_test_apk$', '_test_apk__apk', t) for t in targets] |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 569 # when using --all. | 604 # when using --all. |
| 570 if args.all: | 605 if args.all: |
| 571 main_entries = [e for e in main_entries if e.GetType() == 'android_apk'] | 606 main_entries = [e for e in main_entries if e.GetType() == 'android_apk'] |
| 572 | 607 |
| 573 all_entries = _FindAllProjectEntries(main_entries) | 608 all_entries = _FindAllProjectEntries(main_entries) |
| 574 logging.info('Found %d dependent build_config targets.', len(all_entries)) | 609 logging.info('Found %d dependent build_config targets.', len(all_entries)) |
| 575 entries = _CombineTestEntries(all_entries) | 610 entries = _CombineTestEntries(all_entries) |
| 576 logging.info('Creating %d projects for targets.', len(entries)) | 611 logging.info('Creating %d projects for targets.', len(entries)) |
| 577 | 612 |
| 578 logging.warning('Writing .gradle files...') | 613 logging.warning('Writing .gradle files...') |
| 579 jinja_processor = jinja_template.JinjaProcessor(_FILE_DIR) | |
| 580 build_vars = _ReadBuildVars(output_dir) | 614 build_vars = _ReadBuildVars(output_dir) |
| 581 project_entries = [] | 615 project_entries = [] |
| 582 zip_tuples = [] | 616 zip_tuples = [] |
| 583 generated_inputs = [] | 617 generated_inputs = [] |
| 584 for entry in entries: | 618 for entry in entries: |
| 585 if entry.GetType() not in ('android_apk', 'java_library', 'java_binary'): | 619 if entry.GetType() not in ('android_apk', 'java_library', 'java_binary'): |
| 586 continue | 620 continue |
| 587 | 621 |
| 588 data = _GenerateGradleFile(entry, generator, build_vars, jinja_processor) | 622 data = _GenerateGradleFile(entry, generator, build_vars, jinja_processor) |
| 589 if data: | 623 if data: |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 618 _ExtractZips(generator.project_dir, zip_tuples) | 652 _ExtractZips(generator.project_dir, zip_tuples) |
| 619 | 653 |
| 620 logging.warning('Project created! (%d subprojects)', len(project_entries)) | 654 logging.warning('Project created! (%d subprojects)', len(project_entries)) |
| 621 logging.warning('Generated projects work best with Android Studio 2.2') | 655 logging.warning('Generated projects work best with Android Studio 2.2') |
| 622 logging.warning('For more tips: https://chromium.googlesource.com/chromium' | 656 logging.warning('For more tips: https://chromium.googlesource.com/chromium' |
| 623 '/src.git/+/master/docs/android_studio.md') | 657 '/src.git/+/master/docs/android_studio.md') |
| 624 | 658 |
| 625 | 659 |
| 626 if __name__ == '__main__': | 660 if __name__ == '__main__': |
| 627 main() | 661 main() |
| OLD | NEW |