| 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 16 matching lines...) Expand all Loading... |
| 27 import jinja_template | 27 import jinja_template |
| 28 from util import build_utils | 28 from util import build_utils |
| 29 | 29 |
| 30 | 30 |
| 31 _DEFAULT_ANDROID_MANIFEST_PATH = os.path.join( | 31 _DEFAULT_ANDROID_MANIFEST_PATH = os.path.join( |
| 32 host_paths.DIR_SOURCE_ROOT, 'build', 'android', 'AndroidManifest.xml') | 32 host_paths.DIR_SOURCE_ROOT, 'build', 'android', 'AndroidManifest.xml') |
| 33 _FILE_DIR = os.path.dirname(__file__) | 33 _FILE_DIR = os.path.dirname(__file__) |
| 34 _SRCJARS_SUBDIR = 'extracted-srcjars' | 34 _SRCJARS_SUBDIR = 'extracted-srcjars' |
| 35 _JNI_LIBS_SUBDIR = 'symlinked-libs' | 35 _JNI_LIBS_SUBDIR = 'symlinked-libs' |
| 36 _ARMEABI_SUBDIR = 'armeabi' | 36 _ARMEABI_SUBDIR = 'armeabi' |
| 37 _RES_SUBDIR = 'extracted-res' | |
| 38 | 37 |
| 39 _DEFAULT_TARGETS = [ | 38 _DEFAULT_TARGETS = [ |
| 40 # TODO(agrieve): Requires alternate android.jar to compile. | 39 # TODO(agrieve): Requires alternate android.jar to compile. |
| 41 # '//android_webview:system_webview_apk', | 40 # '//android_webview:system_webview_apk', |
| 42 '//android_webview/test:android_webview_apk', | 41 '//android_webview/test:android_webview_apk', |
| 43 '//android_webview/test:android_webview_test_apk', | 42 '//android_webview/test:android_webview_test_apk', |
| 44 '//base:base_junit_tests', | 43 '//base:base_junit_tests', |
| 45 '//chrome/android:chrome_junit_tests', | 44 '//chrome/android:chrome_junit_tests', |
| 46 '//chrome/android:chrome_public_apk', | 45 '//chrome/android:chrome_public_apk', |
| 47 '//chrome/android:chrome_public_test_apk', | 46 '//chrome/android:chrome_public_test_apk', |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 170 def DepsInfo(self): | 169 def DepsInfo(self): |
| 171 return self.BuildConfig()['deps_info'] | 170 return self.BuildConfig()['deps_info'] |
| 172 | 171 |
| 173 def Gradle(self): | 172 def Gradle(self): |
| 174 return self.BuildConfig()['gradle'] | 173 return self.BuildConfig()['gradle'] |
| 175 | 174 |
| 176 def GetType(self): | 175 def GetType(self): |
| 177 """Returns the target type from its .build_config.""" | 176 """Returns the target type from its .build_config.""" |
| 178 return self.DepsInfo()['type'] | 177 return self.DepsInfo()['type'] |
| 179 | 178 |
| 180 def ResZips(self): | |
| 181 return self.DepsInfo().get('owned_resources_zips') | |
| 182 | |
| 183 def JavaFiles(self): | 179 def JavaFiles(self): |
| 184 if self._java_files is None: | 180 if self._java_files is None: |
| 185 java_sources_file = self.Gradle().get('java_sources_file') | 181 java_sources_file = self.Gradle().get('java_sources_file') |
| 186 java_files = [] | 182 java_files = [] |
| 187 if java_sources_file: | 183 if java_sources_file: |
| 188 java_sources_file = _RebasePath(java_sources_file) | 184 java_sources_file = _RebasePath(java_sources_file) |
| 189 java_files = build_utils.ReadSourcesList(java_sources_file) | 185 java_files = build_utils.ReadSourcesList(java_sources_file) |
| 190 self._java_files = java_files | 186 self._java_files = java_files |
| 191 return self._java_files | 187 return self._java_files |
| 192 | 188 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 208 return jni_libs | 204 return jni_libs |
| 209 | 205 |
| 210 def _GenJavaDirs(self, entry): | 206 def _GenJavaDirs(self, entry): |
| 211 java_dirs, excludes = _CreateJavaSourceDir( | 207 java_dirs, excludes = _CreateJavaSourceDir( |
| 212 constants.GetOutDirectory(), entry.JavaFiles()) | 208 constants.GetOutDirectory(), entry.JavaFiles()) |
| 213 if self.Srcjars(entry): | 209 if self.Srcjars(entry): |
| 214 java_dirs.append( | 210 java_dirs.append( |
| 215 os.path.join(self.EntryOutputDir(entry), _SRCJARS_SUBDIR)) | 211 os.path.join(self.EntryOutputDir(entry), _SRCJARS_SUBDIR)) |
| 216 return java_dirs, excludes | 212 return java_dirs, excludes |
| 217 | 213 |
| 218 def _GenResDirs(self, entry): | |
| 219 res_dirs = list(entry.DepsInfo().get('owned_resources_dirs', [])) | |
| 220 if entry.ResZips(): | |
| 221 res_dirs.append(os.path.join(self.EntryOutputDir(entry), _RES_SUBDIR)) | |
| 222 return res_dirs | |
| 223 | |
| 224 def _Relativize(self, entry, paths): | 214 def _Relativize(self, entry, paths): |
| 225 return _RebasePath(paths, self.EntryOutputDir(entry)) | 215 return _RebasePath(paths, self.EntryOutputDir(entry)) |
| 226 | 216 |
| 227 def EntryOutputDir(self, entry): | 217 def EntryOutputDir(self, entry): |
| 228 return os.path.join(self.project_dir, entry.GradleSubdir()) | 218 return os.path.join(self.project_dir, entry.GradleSubdir()) |
| 229 | 219 |
| 230 def Srcjars(self, entry): | 220 def Srcjars(self, entry): |
| 231 srcjars = _RebasePath(entry.Gradle().get('bundled_srcjars', [])) | 221 srcjars = _RebasePath(entry.Gradle().get('bundled_srcjars', [])) |
| 232 if not self.use_gradle_process_resources: | 222 if not self.use_gradle_process_resources: |
| 233 srcjars += _RebasePath(entry.BuildConfig()['javac']['srcjars']) | 223 srcjars += _RebasePath(entry.BuildConfig()['javac']['srcjars']) |
| 234 return srcjars | 224 return srcjars |
| 235 | 225 |
| 236 def GeneratedInputs(self, entry): | 226 def GeneratedInputs(self, entry): |
| 237 generated_inputs = [] | 227 generated_inputs = [] |
| 238 generated_inputs.extend(self.Srcjars(entry)) | 228 generated_inputs.extend(self.Srcjars(entry)) |
| 239 generated_inputs.extend(_RebasePath(entry.ResZips())) | |
| 240 generated_inputs.extend( | 229 generated_inputs.extend( |
| 241 p for p in entry.JavaFiles() if not p.startswith('..')) | 230 p for p in entry.JavaFiles() if not p.startswith('..')) |
| 242 generated_inputs.extend(entry.Gradle()['dependent_prebuilt_jars']) | 231 generated_inputs.extend(entry.Gradle()['dependent_prebuilt_jars']) |
| 243 return generated_inputs | 232 return generated_inputs |
| 244 | 233 |
| 245 def Generate(self, entry): | 234 def Generate(self, entry): |
| 246 variables = {} | 235 variables = {} |
| 247 android_test_manifest = entry.Gradle().get( | 236 android_test_manifest = entry.Gradle().get( |
| 248 'android_manifest', _DEFAULT_ANDROID_MANIFEST_PATH) | 237 'android_manifest', _DEFAULT_ANDROID_MANIFEST_PATH) |
| 249 variables['android_manifest'] = self._Relativize( | 238 variables['android_manifest'] = self._Relativize( |
| 250 entry, android_test_manifest) | 239 entry, android_test_manifest) |
| 251 java_dirs, excludes = self._GenJavaDirs(entry) | 240 java_dirs, excludes = self._GenJavaDirs(entry) |
| 252 variables['java_dirs'] = self._Relativize(entry, java_dirs) | 241 variables['java_dirs'] = self._Relativize(entry, java_dirs) |
| 253 variables['java_excludes'] = excludes | 242 variables['java_excludes'] = excludes |
| 254 variables['jni_libs'] = self._Relativize(entry, self._GenJniLibs(entry)) | 243 variables['jni_libs'] = self._Relativize(entry, self._GenJniLibs(entry)) |
| 255 variables['res_dirs'] = self._Relativize(entry, self._GenResDirs(entry)) | |
| 256 deps = [_ProjectEntry.FromBuildConfigPath(p) | 244 deps = [_ProjectEntry.FromBuildConfigPath(p) |
| 257 for p in entry.Gradle()['dependent_android_projects']] | 245 for p in entry.Gradle()['dependent_android_projects']] |
| 258 variables['android_project_deps'] = [d.ProjectName() for d in deps] | 246 variables['android_project_deps'] = [d.ProjectName() for d in deps] |
| 259 # TODO(agrieve): Add an option to use interface jars and see if that speeds | 247 # TODO(agrieve): Add an option to use interface jars and see if that speeds |
| 260 # things up at all. | 248 # things up at all. |
| 261 variables['prebuilts'] = self._Relativize( | 249 variables['prebuilts'] = self._Relativize( |
| 262 entry, entry.Gradle()['dependent_prebuilt_jars']) | 250 entry, entry.Gradle()['dependent_prebuilt_jars']) |
| 263 deps = [_ProjectEntry.FromBuildConfigPath(p) | 251 deps = [_ProjectEntry.FromBuildConfigPath(p) |
| 264 for p in entry.Gradle()['dependent_java_projects']] | 252 for p in entry.Gradle()['dependent_java_projects']] |
| 265 variables['java_project_deps'] = [d.ProjectName() for d in deps] | 253 variables['java_project_deps'] = [d.ProjectName() for d in deps] |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 441 lines.append('') | 429 lines.append('') |
| 442 | 430 |
| 443 for entry in project_entries: | 431 for entry in project_entries: |
| 444 # Example target: android_webview:android_webview_java__build_config | 432 # Example target: android_webview:android_webview_java__build_config |
| 445 lines.append('include ":%s"' % entry.ProjectName()) | 433 lines.append('include ":%s"' % entry.ProjectName()) |
| 446 lines.append('project(":%s").projectDir = new File(settingsDir, "%s")' % | 434 lines.append('project(":%s").projectDir = new File(settingsDir, "%s")' % |
| 447 (entry.ProjectName(), entry.GradleSubdir())) | 435 (entry.ProjectName(), entry.GradleSubdir())) |
| 448 return '\n'.join(lines) | 436 return '\n'.join(lines) |
| 449 | 437 |
| 450 | 438 |
| 451 def _ExtractFile(zip_path, extracted_path): | 439 def _ExtractSrcjars(entry_output_dir, srcjar_tuples): |
| 452 logging.info('Extracting %s to %s', zip_path, extracted_path) | |
| 453 with zipfile.ZipFile(zip_path) as z: | |
| 454 z.extractall(extracted_path) | |
| 455 | |
| 456 | |
| 457 def _ExtractZips(entry_output_dir, zip_tuples): | |
| 458 """Extracts all srcjars to the directory given by the tuples.""" | 440 """Extracts all srcjars to the directory given by the tuples.""" |
| 459 extracted_paths = set(s[1] for s in zip_tuples) | 441 extracted_paths = set(s[1] for s in srcjar_tuples) |
| 460 for extracted_path in extracted_paths: | 442 for extracted_path in extracted_paths: |
| 461 assert _IsSubpathOf(extracted_path, entry_output_dir) | 443 assert _IsSubpathOf(extracted_path, entry_output_dir) |
| 462 shutil.rmtree(extracted_path, True) | 444 shutil.rmtree(extracted_path, True) |
| 463 | 445 |
| 464 for zip_path, extracted_path in zip_tuples: | 446 for srcjar_path, extracted_path in srcjar_tuples: |
| 465 _ExtractFile(zip_path, extracted_path) | 447 logging.info('Extracting %s to %s', srcjar_path, extracted_path) |
| 448 with zipfile.ZipFile(srcjar_path) as z: |
| 449 z.extractall(extracted_path) |
| 466 | 450 |
| 467 | 451 |
| 468 def _FindAllProjectEntries(main_entries): | 452 def _FindAllProjectEntries(main_entries): |
| 469 """Returns the list of all _ProjectEntry instances given the root project.""" | 453 """Returns the list of all _ProjectEntry instances given the root project.""" |
| 470 found = set() | 454 found = set() |
| 471 to_scan = list(main_entries) | 455 to_scan = list(main_entries) |
| 472 while to_scan: | 456 while to_scan: |
| 473 cur_entry = to_scan.pop() | 457 cur_entry = to_scan.pop() |
| 474 if cur_entry in found: | 458 if cur_entry in found: |
| 475 continue | 459 continue |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 570 | 554 |
| 571 all_entries = _FindAllProjectEntries(main_entries) | 555 all_entries = _FindAllProjectEntries(main_entries) |
| 572 logging.info('Found %d dependent build_config targets.', len(all_entries)) | 556 logging.info('Found %d dependent build_config targets.', len(all_entries)) |
| 573 entries = _CombineTestEntries(all_entries) | 557 entries = _CombineTestEntries(all_entries) |
| 574 logging.info('Creating %d projects for targets.', len(entries)) | 558 logging.info('Creating %d projects for targets.', len(entries)) |
| 575 | 559 |
| 576 logging.warning('Writing .gradle files...') | 560 logging.warning('Writing .gradle files...') |
| 577 jinja_processor = jinja_template.JinjaProcessor(_FILE_DIR) | 561 jinja_processor = jinja_template.JinjaProcessor(_FILE_DIR) |
| 578 build_vars = _ReadBuildVars(output_dir) | 562 build_vars = _ReadBuildVars(output_dir) |
| 579 project_entries = [] | 563 project_entries = [] |
| 580 zip_tuples = [] | 564 srcjar_tuples = [] |
| 581 generated_inputs = [] | 565 generated_inputs = [] |
| 582 for entry in entries: | 566 for entry in entries: |
| 583 if entry.GetType() not in ('android_apk', 'java_library', 'java_binary'): | 567 if entry.GetType() not in ('android_apk', 'java_library', 'java_binary'): |
| 584 continue | 568 continue |
| 585 | 569 |
| 586 data = _GenerateGradleFile(entry, generator, build_vars, jinja_processor) | 570 data = _GenerateGradleFile(entry, generator, build_vars, jinja_processor) |
| 587 if data: | 571 if data: |
| 588 project_entries.append(entry) | 572 project_entries.append(entry) |
| 589 # Build all paths references by .gradle that exist within output_dir. | 573 # Build all paths references by .gradle that exist within output_dir. |
| 590 generated_inputs.extend(generator.GeneratedInputs(entry)) | 574 generated_inputs.extend(generator.GeneratedInputs(entry)) |
| 591 zip_tuples.extend( | 575 srcjar_tuples.extend( |
| 592 (s, os.path.join(generator.EntryOutputDir(entry), _SRCJARS_SUBDIR)) | 576 (s, os.path.join(generator.EntryOutputDir(entry), _SRCJARS_SUBDIR)) |
| 593 for s in generator.Srcjars(entry)) | 577 for s in generator.Srcjars(entry)) |
| 594 zip_tuples.extend( | |
| 595 (s, os.path.join(generator.EntryOutputDir(entry), _RES_SUBDIR)) | |
| 596 for s in _RebasePath(entry.ResZips())) | |
| 597 _WriteFile( | 578 _WriteFile( |
| 598 os.path.join(generator.EntryOutputDir(entry), 'build.gradle'), data) | 579 os.path.join(generator.EntryOutputDir(entry), 'build.gradle'), data) |
| 599 | 580 |
| 600 _WriteFile(os.path.join(generator.project_dir, 'build.gradle'), | 581 _WriteFile(os.path.join(generator.project_dir, 'build.gradle'), |
| 601 _GenerateRootGradle(jinja_processor)) | 582 _GenerateRootGradle(jinja_processor)) |
| 602 | 583 |
| 603 _WriteFile(os.path.join(generator.project_dir, 'settings.gradle'), | 584 _WriteFile(os.path.join(generator.project_dir, 'settings.gradle'), |
| 604 _GenerateSettingsGradle(project_entries)) | 585 _GenerateSettingsGradle(project_entries)) |
| 605 | 586 |
| 606 sdk_path = _RebasePath(build_vars['android_sdk_root']) | 587 sdk_path = _RebasePath(build_vars['android_sdk_root']) |
| 607 _WriteFile(os.path.join(generator.project_dir, 'local.properties'), | 588 _WriteFile(os.path.join(generator.project_dir, 'local.properties'), |
| 608 _GenerateLocalProperties(sdk_path)) | 589 _GenerateLocalProperties(sdk_path)) |
| 609 | 590 |
| 610 if generated_inputs: | 591 if generated_inputs: |
| 611 logging.warning('Building generated source files...') | 592 logging.warning('Building generated source files...') |
| 612 targets = _RebasePath(generated_inputs, output_dir) | 593 targets = _RebasePath(generated_inputs, output_dir) |
| 613 _RunNinja(output_dir, targets) | 594 _RunNinja(output_dir, targets) |
| 614 | 595 |
| 615 if zip_tuples: | 596 if srcjar_tuples: |
| 616 _ExtractZips(generator.project_dir, zip_tuples) | 597 _ExtractSrcjars(generator.project_dir, srcjar_tuples) |
| 617 | 598 |
| 618 logging.warning('Project created! (%d subprojects)', len(project_entries)) | 599 logging.warning('Project created! (%d subprojects)', len(project_entries)) |
| 619 logging.warning('Generated projects work best with Android Studio 2.2') | 600 logging.warning('Generated projects work best with Android Studio 2.2') |
| 620 logging.warning('For more tips: https://chromium.googlesource.com/chromium' | 601 logging.warning('For more tips: https://chromium.googlesource.com/chromium' |
| 621 '/src.git/+/master/docs/android_studio.md') | 602 '/src.git/+/master/docs/android_studio.md') |
| 622 | 603 |
| 623 | 604 |
| 624 if __name__ == '__main__': | 605 if __name__ == '__main__': |
| 625 main() | 606 main() |
| OLD | NEW |