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

Side by Side Diff: build/android/gradle/generate_gradle.py

Issue 2687453002: Reland "Android: Add owned resources to android studio" (Closed)
Patch Set: Changes Created 3 years, 10 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 unified diff | Download patch
« no previous file with comments | « build/android/gradle/android.jinja ('k') | docs/android_studio.md » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 logging 10 import logging
(...skipping 16 matching lines...) Expand all
27 from util import build_utils 27 from util import build_utils
28 28
29 29
30 _DEFAULT_ANDROID_MANIFEST_PATH = os.path.join( 30 _DEFAULT_ANDROID_MANIFEST_PATH = os.path.join(
31 host_paths.DIR_SOURCE_ROOT, 'build', 'android', 'AndroidManifest.xml') 31 host_paths.DIR_SOURCE_ROOT, 'build', 'android', 'AndroidManifest.xml')
32 _FILE_DIR = os.path.dirname(__file__) 32 _FILE_DIR = os.path.dirname(__file__)
33 _JAVA_SUBDIR = 'symlinked-java' 33 _JAVA_SUBDIR = 'symlinked-java'
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'
37 38
38 _DEFAULT_TARGETS = [ 39 _DEFAULT_TARGETS = [
39 # TODO(agrieve): Requires alternate android.jar to compile. 40 # TODO(agrieve): Requires alternate android.jar to compile.
40 # '//android_webview:system_webview_apk', 41 # '//android_webview:system_webview_apk',
41 '//android_webview/test:android_webview_apk', 42 '//android_webview/test:android_webview_apk',
42 '//android_webview/test:android_webview_test_apk', 43 '//android_webview/test:android_webview_test_apk',
43 '//base:base_junit_tests', 44 '//base:base_junit_tests',
44 '//chrome/android:chrome_junit_tests', 45 '//chrome/android:chrome_junit_tests',
45 '//chrome/android:chrome_public_apk', 46 '//chrome/android:chrome_public_apk',
46 '//chrome/android:chrome_public_test_apk', 47 '//chrome/android:chrome_public_test_apk',
47 '//chrome/android:chrome_sync_shell_apk', 48 '//chrome/android:chrome_sync_shell_apk',
48 '//chrome/android:chrome_sync_shell_test_apk', 49 '//chrome/android:chrome_sync_shell_test_apk',
49 '//content/public/android:content_junit_tests', 50 '//content/public/android:content_junit_tests',
50 '//content/shell/android:content_shell_apk', 51 '//content/shell/android:content_shell_apk',
51 ] 52 ]
52 53
53 54
54 def _TemplatePath(name): 55 def _TemplatePath(name):
55 return os.path.join(_FILE_DIR, '{}.jinja'.format(name)) 56 return os.path.join(_FILE_DIR, '{}.jinja'.format(name))
56 57
57 58
58 def _RebasePath(path_or_list, new_cwd=None, old_cwd=None): 59 def _RebasePath(path_or_list, new_cwd=None, old_cwd=None):
59 """Makes the given path(s) relative to new_cwd, or absolute if not specified. 60 """Makes the given path(s) relative to new_cwd, or absolute if not specified.
60 61
61 If new_cwd is not specified, absolute paths are returned. 62 If new_cwd is not specified, absolute paths are returned.
62 If old_cwd is not specified, constants.GetOutDirectory() is assumed. 63 If old_cwd is not specified, constants.GetOutDirectory() is assumed.
63 """ 64 """
65 if not path_or_list:
agrieve 2017/02/09 15:29:31 The following line says: if not isinstance(path_o
Peter Wen 2017/02/09 16:42:05 Opps, you're right. Fixed now.
66 return []
64 if not isinstance(path_or_list, basestring): 67 if not isinstance(path_or_list, basestring):
65 return [_RebasePath(p, new_cwd, old_cwd) for p in path_or_list] 68 return [_RebasePath(p, new_cwd, old_cwd) for p in path_or_list]
66 if old_cwd is None: 69 if old_cwd is None:
67 old_cwd = constants.GetOutDirectory() 70 old_cwd = constants.GetOutDirectory()
68 old_cwd = os.path.abspath(old_cwd) 71 old_cwd = os.path.abspath(old_cwd)
69 if new_cwd: 72 if new_cwd:
70 new_cwd = os.path.abspath(new_cwd) 73 new_cwd = os.path.abspath(new_cwd)
71 return os.path.relpath(os.path.join(old_cwd, path_or_list), new_cwd) 74 return os.path.relpath(os.path.join(old_cwd, path_or_list), new_cwd)
72 return os.path.abspath(os.path.join(old_cwd, path_or_list)) 75 return os.path.abspath(os.path.join(old_cwd, path_or_list))
73 76
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
169 def DepsInfo(self): 172 def DepsInfo(self):
170 return self.BuildConfig()['deps_info'] 173 return self.BuildConfig()['deps_info']
171 174
172 def Gradle(self): 175 def Gradle(self):
173 return self.BuildConfig()['gradle'] 176 return self.BuildConfig()['gradle']
174 177
175 def GetType(self): 178 def GetType(self):
176 """Returns the target type from its .build_config.""" 179 """Returns the target type from its .build_config."""
177 return self.DepsInfo()['type'] 180 return self.DepsInfo()['type']
178 181
182 def ResZips(self):
183 return self.DepsInfo().get('owned_resources_zips')
184
179 def JavaFiles(self): 185 def JavaFiles(self):
180 if self._java_files is None: 186 if self._java_files is None:
181 java_sources_file = self.Gradle().get('java_sources_file') 187 java_sources_file = self.Gradle().get('java_sources_file')
182 java_files = [] 188 java_files = []
183 if java_sources_file: 189 if java_sources_file:
184 java_sources_file = _RebasePath(java_sources_file) 190 java_sources_file = _RebasePath(java_sources_file)
185 java_files = build_utils.ReadSourcesList(java_sources_file) 191 java_files = build_utils.ReadSourcesList(java_sources_file)
186 self._java_files = java_files 192 self._java_files = java_files
187 return self._java_files 193 return self._java_files
188 194
(...skipping 16 matching lines...) Expand all
205 211
206 def _GenJavaDirs(self, entry): 212 def _GenJavaDirs(self, entry):
207 java_dirs = _CreateJavaSourceDir( 213 java_dirs = _CreateJavaSourceDir(
208 constants.GetOutDirectory(), self.EntryOutputDir(entry), 214 constants.GetOutDirectory(), self.EntryOutputDir(entry),
209 entry.JavaFiles()) 215 entry.JavaFiles())
210 if self.Srcjars(entry): 216 if self.Srcjars(entry):
211 java_dirs.append( 217 java_dirs.append(
212 os.path.join(self.EntryOutputDir(entry), _SRCJARS_SUBDIR)) 218 os.path.join(self.EntryOutputDir(entry), _SRCJARS_SUBDIR))
213 return java_dirs 219 return java_dirs
214 220
221 def _GenResDirs(self, entry):
222 res_dirs = list(entry.DepsInfo().get('owned_resources_dirs', []))
223 if entry.ResZips():
224 res_dirs.append(os.path.join(self.EntryOutputDir(entry), _RES_SUBDIR))
225 return res_dirs
226
215 def _Relativize(self, entry, paths): 227 def _Relativize(self, entry, paths):
216 return _RebasePath(paths, self.EntryOutputDir(entry)) 228 return _RebasePath(paths, self.EntryOutputDir(entry))
217 229
218 def EntryOutputDir(self, entry): 230 def EntryOutputDir(self, entry):
219 return os.path.join(self.project_dir, entry.GradleSubdir()) 231 return os.path.join(self.project_dir, entry.GradleSubdir())
220 232
221 def Srcjars(self, entry): 233 def Srcjars(self, entry):
222 srcjars = _RebasePath(entry.Gradle().get('bundled_srcjars', [])) 234 srcjars = _RebasePath(entry.Gradle().get('bundled_srcjars', []))
223 if not self.use_gradle_process_resources: 235 if not self.use_gradle_process_resources:
224 srcjars += _RebasePath(entry.BuildConfig()['javac']['srcjars']) 236 srcjars += _RebasePath(entry.BuildConfig()['javac']['srcjars'])
225 return srcjars 237 return srcjars
226 238
227 def GeneratedInputs(self, entry): 239 def GeneratedInputs(self, entry):
228 generated_inputs = [] 240 generated_inputs = []
229 generated_inputs.extend(self.Srcjars(entry)) 241 generated_inputs.extend(self.Srcjars(entry))
242 generated_inputs.extend(_RebasePath(entry.ResZips()))
230 generated_inputs.extend( 243 generated_inputs.extend(
231 p for p in entry.JavaFiles() if not p.startswith('..')) 244 p for p in entry.JavaFiles() if not p.startswith('..'))
232 generated_inputs.extend(entry.Gradle()['dependent_prebuilt_jars']) 245 generated_inputs.extend(entry.Gradle()['dependent_prebuilt_jars'])
233 return generated_inputs 246 return generated_inputs
234 247
235 def Generate(self, entry): 248 def Generate(self, entry):
236 variables = {} 249 variables = {}
237 android_test_manifest = entry.Gradle().get( 250 android_test_manifest = entry.Gradle().get(
238 'android_manifest', _DEFAULT_ANDROID_MANIFEST_PATH) 251 'android_manifest', _DEFAULT_ANDROID_MANIFEST_PATH)
239 variables['android_manifest'] = self._Relativize( 252 variables['android_manifest'] = self._Relativize(
240 entry, android_test_manifest) 253 entry, android_test_manifest)
241 variables['java_dirs'] = self._Relativize(entry, self._GenJavaDirs(entry)) 254 variables['java_dirs'] = self._Relativize(entry, self._GenJavaDirs(entry))
242 variables['jni_libs'] = self._Relativize(entry, self._GenJniLibs(entry)) 255 variables['jni_libs'] = self._Relativize(entry, self._GenJniLibs(entry))
256 variables['res_dirs'] = self._Relativize(entry, self._GenResDirs(entry))
243 deps = [_ProjectEntry.FromBuildConfigPath(p) 257 deps = [_ProjectEntry.FromBuildConfigPath(p)
244 for p in entry.Gradle()['dependent_android_projects']] 258 for p in entry.Gradle()['dependent_android_projects']]
245 variables['android_project_deps'] = [d.ProjectName() for d in deps] 259 variables['android_project_deps'] = [d.ProjectName() for d in deps]
246 # TODO(agrieve): Add an option to use interface jars and see if that speeds 260 # TODO(agrieve): Add an option to use interface jars and see if that speeds
247 # things up at all. 261 # things up at all.
248 variables['prebuilts'] = self._Relativize( 262 variables['prebuilts'] = self._Relativize(
249 entry, entry.Gradle()['dependent_prebuilt_jars']) 263 entry, entry.Gradle()['dependent_prebuilt_jars'])
250 deps = [_ProjectEntry.FromBuildConfigPath(p) 264 deps = [_ProjectEntry.FromBuildConfigPath(p)
251 for p in entry.Gradle()['dependent_java_projects']] 265 for p in entry.Gradle()['dependent_java_projects']]
252 variables['java_project_deps'] = [d.ProjectName() for d in deps] 266 variables['java_project_deps'] = [d.ProjectName() for d in deps]
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
422 lines.append('') 436 lines.append('')
423 437
424 for entry in project_entries: 438 for entry in project_entries:
425 # Example target: android_webview:android_webview_java__build_config 439 # Example target: android_webview:android_webview_java__build_config
426 lines.append('include ":%s"' % entry.ProjectName()) 440 lines.append('include ":%s"' % entry.ProjectName())
427 lines.append('project(":%s").projectDir = new File(settingsDir, "%s")' % 441 lines.append('project(":%s").projectDir = new File(settingsDir, "%s")' %
428 (entry.ProjectName(), entry.GradleSubdir())) 442 (entry.ProjectName(), entry.GradleSubdir()))
429 return '\n'.join(lines) 443 return '\n'.join(lines)
430 444
431 445
432 def _ExtractSrcjars(entry_output_dir, srcjar_tuples): 446 def _ExtractFile(zip_path, extracted_path):
447 logging.info('Extracting %s to %s', zip_path, extracted_path)
448 with zipfile.ZipFile(zip_path) as z:
449 z.extractall(extracted_path)
450
451
452 def _ExtractZips(entry_output_dir, zip_tuples):
433 """Extracts all srcjars to the directory given by the tuples.""" 453 """Extracts all srcjars to the directory given by the tuples."""
434 extracted_paths = set(s[1] for s in srcjar_tuples) 454 extracted_paths = set(s[1] for s in zip_tuples)
435 for extracted_path in extracted_paths: 455 for extracted_path in extracted_paths:
436 assert _IsSubpathOf(extracted_path, entry_output_dir) 456 assert _IsSubpathOf(extracted_path, entry_output_dir)
437 shutil.rmtree(extracted_path, True) 457 shutil.rmtree(extracted_path, True)
438 458
439 for srcjar_path, extracted_path in srcjar_tuples: 459 for zip_path, extracted_path in zip_tuples:
440 logging.info('Extracting %s to %s', srcjar_path, extracted_path) 460 _ExtractFile(zip_path, extracted_path)
441 with zipfile.ZipFile(srcjar_path) as z:
442 z.extractall(extracted_path)
443 461
444 462
445 def _FindAllProjectEntries(main_entries): 463 def _FindAllProjectEntries(main_entries):
446 """Returns the list of all _ProjectEntry instances given the root project.""" 464 """Returns the list of all _ProjectEntry instances given the root project."""
447 found = set() 465 found = set()
448 to_scan = list(main_entries) 466 to_scan = list(main_entries)
449 while to_scan: 467 while to_scan:
450 cur_entry = to_scan.pop() 468 cur_entry = to_scan.pop()
451 if cur_entry in found: 469 if cur_entry in found:
452 continue 470 continue
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 565
548 all_entries = _FindAllProjectEntries(main_entries) 566 all_entries = _FindAllProjectEntries(main_entries)
549 logging.info('Found %d dependent build_config targets.', len(all_entries)) 567 logging.info('Found %d dependent build_config targets.', len(all_entries))
550 entries = _CombineTestEntries(all_entries) 568 entries = _CombineTestEntries(all_entries)
551 logging.info('Creating %d projects for targets.', len(entries)) 569 logging.info('Creating %d projects for targets.', len(entries))
552 570
553 logging.warning('Writing .gradle files...') 571 logging.warning('Writing .gradle files...')
554 jinja_processor = jinja_template.JinjaProcessor(_FILE_DIR) 572 jinja_processor = jinja_template.JinjaProcessor(_FILE_DIR)
555 build_vars = _ReadBuildVars(output_dir) 573 build_vars = _ReadBuildVars(output_dir)
556 project_entries = [] 574 project_entries = []
557 srcjar_tuples = [] 575 zip_tuples = []
558 generated_inputs = [] 576 generated_inputs = []
559 for entry in entries: 577 for entry in entries:
560 if entry.GetType() not in ('android_apk', 'java_library', 'java_binary'): 578 if entry.GetType() not in ('android_apk', 'java_library', 'java_binary'):
561 continue 579 continue
562 580
563 data = _GenerateGradleFile(entry, generator, build_vars, jinja_processor) 581 data = _GenerateGradleFile(entry, generator, build_vars, jinja_processor)
564 if data: 582 if data:
565 project_entries.append(entry) 583 project_entries.append(entry)
566 # Build all paths references by .gradle that exist within output_dir. 584 # Build all paths references by .gradle that exist within output_dir.
567 generated_inputs.extend(generator.GeneratedInputs(entry)) 585 generated_inputs.extend(generator.GeneratedInputs(entry))
568 srcjar_tuples.extend( 586 zip_tuples.extend(
569 (s, os.path.join(generator.EntryOutputDir(entry), _SRCJARS_SUBDIR)) 587 (s, os.path.join(generator.EntryOutputDir(entry), _SRCJARS_SUBDIR))
570 for s in generator.Srcjars(entry)) 588 for s in generator.Srcjars(entry))
589 zip_tuples.extend(
590 (s, os.path.join(generator.EntryOutputDir(entry), _RES_SUBDIR))
591 for s in _RebasePath(entry.ResZips()))
571 _WriteFile( 592 _WriteFile(
572 os.path.join(generator.EntryOutputDir(entry), 'build.gradle'), data) 593 os.path.join(generator.EntryOutputDir(entry), 'build.gradle'), data)
573 594
574 _WriteFile(os.path.join(generator.project_dir, 'build.gradle'), 595 _WriteFile(os.path.join(generator.project_dir, 'build.gradle'),
575 _GenerateRootGradle(jinja_processor)) 596 _GenerateRootGradle(jinja_processor))
576 597
577 _WriteFile(os.path.join(generator.project_dir, 'settings.gradle'), 598 _WriteFile(os.path.join(generator.project_dir, 'settings.gradle'),
578 _GenerateSettingsGradle(project_entries)) 599 _GenerateSettingsGradle(project_entries))
579 600
580 sdk_path = _RebasePath(build_vars['android_sdk_root']) 601 sdk_path = _RebasePath(build_vars['android_sdk_root'])
581 _WriteFile(os.path.join(generator.project_dir, 'local.properties'), 602 _WriteFile(os.path.join(generator.project_dir, 'local.properties'),
582 _GenerateLocalProperties(sdk_path)) 603 _GenerateLocalProperties(sdk_path))
583 604
584 if generated_inputs: 605 if generated_inputs:
585 logging.warning('Building generated source files...') 606 logging.warning('Building generated source files...')
586 targets = _RebasePath(generated_inputs, output_dir) 607 targets = _RebasePath(generated_inputs, output_dir)
587 _RunNinja(output_dir, targets) 608 _RunNinja(output_dir, targets)
588 609
589 if srcjar_tuples: 610 if zip_tuples:
590 _ExtractSrcjars(generator.project_dir, srcjar_tuples) 611 _ExtractZips(generator.project_dir, zip_tuples)
591 612
592 logging.warning('Project created! (%d subprojects)', len(project_entries)) 613 logging.warning('Project created! (%d subprojects)', len(project_entries))
593 logging.warning('Generated projects work best with Android Studio 2.2') 614 logging.warning('Generated projects work best with Android Studio 2.2')
594 logging.warning('For more tips: https://chromium.googlesource.com/chromium' 615 logging.warning('For more tips: https://chromium.googlesource.com/chromium'
595 '/src.git/+/master/docs/android_studio.md') 616 '/src.git/+/master/docs/android_studio.md')
596 617
597 618
598 if __name__ == '__main__': 619 if __name__ == '__main__':
599 main() 620 main()
OLDNEW
« no previous file with comments | « build/android/gradle/android.jinja ('k') | docs/android_studio.md » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698