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 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 return self.BuildConfig()['gradle'] | 190 return self.BuildConfig()['gradle'] |
191 | 191 |
192 def Javac(self): | 192 def Javac(self): |
193 return self.BuildConfig()['javac'] | 193 return self.BuildConfig()['javac'] |
194 | 194 |
195 def GetType(self): | 195 def GetType(self): |
196 """Returns the target type from its .build_config.""" | 196 """Returns the target type from its .build_config.""" |
197 return self.DepsInfo()['type'] | 197 return self.DepsInfo()['type'] |
198 | 198 |
199 def ResZips(self): | 199 def ResZips(self): |
200 return self.DepsInfo().get('owned_resources_zips') | 200 return self.DepsInfo().get('owned_resources_zips', []) |
| 201 |
| 202 def ResDirs(self): |
| 203 return self.DepsInfo().get('owned_resources_dirs', []) |
201 | 204 |
202 def JavaFiles(self): | 205 def JavaFiles(self): |
203 if self._java_files is None: | 206 if self._java_files is None: |
204 java_sources_file = self.Gradle().get('java_sources_file') | 207 java_sources_file = self.Gradle().get('java_sources_file') |
205 java_files = [] | 208 java_files = [] |
206 if java_sources_file: | 209 if java_sources_file: |
207 java_sources_file = _RebasePath(java_sources_file) | 210 java_sources_file = _RebasePath(java_sources_file) |
208 java_files = build_utils.ReadSourcesList(java_sources_file) | 211 java_files = build_utils.ReadSourcesList(java_sources_file) |
209 self._java_files = java_files | 212 self._java_files = java_files |
210 return self._java_files | 213 return self._java_files |
211 | 214 |
212 def GeneratedJavaFiles(self): | 215 def GeneratedJavaFiles(self): |
213 return [p for p in self.JavaFiles() if not p.startswith('..')] | 216 return [p for p in self.JavaFiles() if not p.startswith('..')] |
214 | 217 |
215 def PrebuiltJars(self): | 218 def PrebuiltJars(self): |
216 return self.Gradle()['dependent_prebuilt_jars'] | 219 return self.Gradle().get('dependent_prebuilt_jars', []) |
217 | 220 |
218 def AllEntries(self): | 221 def AllEntries(self): |
219 """Returns a list of all entries that the current entry depends on. | 222 """Returns a list of all entries that the current entry depends on. |
220 | 223 |
221 This includes the entry itself to make iterating simpler.""" | 224 This includes the entry itself to make iterating simpler.""" |
222 if self._all_entries is None: | 225 if self._all_entries is None: |
223 logging.debug('Generating entries for %s', self.GnTarget()) | 226 logging.debug('Generating entries for %s', self.GnTarget()) |
224 deps = [_ProjectEntry.FromBuildConfigPath(p) | 227 deps = [_ProjectEntry.FromBuildConfigPath(p) |
225 for p in self.Gradle()['dependent_android_projects']] | 228 for p in self.Gradle()['dependent_android_projects']] |
226 deps.extend(_ProjectEntry.FromBuildConfigPath(p) | 229 deps.extend(_ProjectEntry.FromBuildConfigPath(p) |
227 for p in self.Gradle()['dependent_java_projects']) | 230 for p in self.Gradle()['dependent_java_projects']) |
228 all_entries = set() | 231 all_entries = set() |
229 for dep in deps: | 232 for dep in deps: |
230 all_entries.update(dep.AllEntries()) | 233 all_entries.update(dep.AllEntries()) |
231 all_entries.add(self) | 234 all_entries.add(self) |
232 self._all_entries = list(all_entries) | 235 self._all_entries = list(all_entries) |
233 return self._all_entries | 236 return self._all_entries |
234 | 237 |
235 | 238 |
236 class _ProjectContextGenerator(object): | 239 class _ProjectContextGenerator(object): |
237 """Helper class to generate gradle build files""" | 240 """Helper class to generate gradle build files""" |
238 def __init__(self, project_dir, build_vars, use_gradle_process_resources, | 241 def __init__(self, project_dir, build_vars, use_gradle_process_resources, |
239 jinja_processor): | 242 jinja_processor, split_projects): |
240 self.project_dir = project_dir | 243 self.project_dir = project_dir |
241 self.build_vars = build_vars | 244 self.build_vars = build_vars |
242 self.use_gradle_process_resources = use_gradle_process_resources | 245 self.use_gradle_process_resources = use_gradle_process_resources |
243 self.jinja_processor = jinja_processor | 246 self.jinja_processor = jinja_processor |
| 247 self.split_projects = split_projects |
244 | 248 |
245 def _GenJniLibs(self, entry): | 249 def _GenJniLibs(self, root_entry): |
246 native_section = entry.BuildConfig().get('native') | 250 libraries = [] |
247 if native_section: | 251 for entry in self._GetEntries(root_entry): |
248 jni_libs = _CreateJniLibsDir( | 252 libraries += entry.BuildConfig().get('native', []) |
249 constants.GetOutDirectory(), self.EntryOutputDir(entry), | 253 if libraries: |
250 native_section.get('libraries')) | 254 return _CreateJniLibsDir(constants.GetOutDirectory(), |
251 else: | 255 self.EntryOutputDir(root_entry), libraries) |
252 jni_libs = [] | 256 return [] |
253 return jni_libs | |
254 | 257 |
255 def _GenJavaDirs(self, entry): | 258 def _GenJavaDirs(self, root_entry): |
| 259 java_files = [] |
| 260 for entry in self._GetEntries(root_entry): |
| 261 java_files += entry.JavaFiles() |
256 java_dirs, excludes = _ComputeJavaSourceDirsAndExcludes( | 262 java_dirs, excludes = _ComputeJavaSourceDirsAndExcludes( |
257 constants.GetOutDirectory(), entry.JavaFiles()) | 263 constants.GetOutDirectory(), java_files) |
258 if self.Srcjars(entry): | |
259 java_dirs.append( | |
260 os.path.join(self.EntryOutputDir(entry), _SRCJARS_SUBDIR)) | |
261 return java_dirs, excludes | 264 return java_dirs, excludes |
262 | 265 |
263 def _GenResDirs(self, entry): | |
264 res_dirs = list(entry.DepsInfo().get('owned_resources_dirs', [])) | |
265 if entry.ResZips(): | |
266 res_dirs.append(os.path.join(self.EntryOutputDir(entry), _RES_SUBDIR)) | |
267 return res_dirs | |
268 | |
269 def _GenCustomManifest(self, entry): | 266 def _GenCustomManifest(self, entry): |
270 """Returns the path to the generated AndroidManifest.xml. | 267 """Returns the path to the generated AndroidManifest.xml. |
271 | 268 |
272 Gradle uses package id from manifest when generating R.class. So, we need | 269 Gradle uses package id from manifest when generating R.class. So, we need |
273 to generate a custom manifest if we let gradle process resources. We cannot | 270 to generate a custom manifest if we let gradle process resources. We cannot |
274 simply set android.defaultConfig.applicationId because it is not supported | 271 simply set android.defaultConfig.applicationId because it is not supported |
275 for library targets.""" | 272 for library targets.""" |
276 resource_packages = entry.Javac().get('resource_packages') | 273 resource_packages = entry.Javac().get('resource_packages') |
277 if not resource_packages: | 274 if not resource_packages: |
278 logging.debug('Target ' + entry.GnTarget() + ' includes resources from ' | 275 logging.debug('Target ' + entry.GnTarget() + ' includes resources from ' |
(...skipping 11 matching lines...) Expand all Loading... |
290 output_file = os.path.join( | 287 output_file = os.path.join( |
291 self.EntryOutputDir(entry), 'AndroidManifest.xml') | 288 self.EntryOutputDir(entry), 'AndroidManifest.xml') |
292 data = self.jinja_processor.Render(_TemplatePath('manifest'), variables) | 289 data = self.jinja_processor.Render(_TemplatePath('manifest'), variables) |
293 _WriteFile(output_file, data) | 290 _WriteFile(output_file, data) |
294 | 291 |
295 return output_file | 292 return output_file |
296 | 293 |
297 def _Relativize(self, entry, paths): | 294 def _Relativize(self, entry, paths): |
298 return _RebasePath(paths, self.EntryOutputDir(entry)) | 295 return _RebasePath(paths, self.EntryOutputDir(entry)) |
299 | 296 |
300 def EntryOutputDir(self, entry): | 297 def _Srcjars(self, entry): |
301 return os.path.join(self.project_dir, entry.GradleSubdir()) | |
302 | |
303 def Srcjars(self, entry): | |
304 srcjars = _RebasePath(entry.Gradle().get('bundled_srcjars', [])) | 298 srcjars = _RebasePath(entry.Gradle().get('bundled_srcjars', [])) |
305 if not self.use_gradle_process_resources: | 299 if not self.use_gradle_process_resources: |
306 srcjars += _RebasePath(entry.BuildConfig()['javac']['srcjars']) | 300 srcjars += _RebasePath(entry.BuildConfig()['javac']['srcjars']) |
307 return srcjars | 301 return srcjars |
308 | 302 |
309 def GeneratedInputs(self, entry): | 303 def _GetEntries(self, entry): |
310 generated_inputs = [] | 304 if self.split_projects: |
311 generated_inputs.extend(self.Srcjars(entry)) | 305 return [entry] |
312 generated_inputs.extend(_RebasePath(entry.ResZips())) | 306 return entry.AllEntries() |
313 generated_inputs.extend(entry.GeneratedJavaFiles()) | |
314 generated_inputs.extend(entry.PrebuiltJars()) | |
315 return generated_inputs | |
316 | 307 |
317 def Generate(self, entry): | 308 def EntryOutputDir(self, entry): |
318 variables = {} | 309 return os.path.join(self.project_dir, entry.GradleSubdir()) |
319 java_dirs, excludes = self._GenJavaDirs(entry) | 310 |
320 variables['java_dirs'] = self._Relativize(entry, java_dirs) | 311 def AllSrcjars(self, root_entry): |
321 variables['java_excludes'] = excludes | 312 srcjars = [] |
322 variables['jni_libs'] = self._Relativize(entry, self._GenJniLibs(entry)) | 313 for entry in self._GetEntries(root_entry): |
323 variables['res_dirs'] = self._Relativize(entry, self._GenResDirs(entry)) | 314 srcjars += self._Srcjars(entry) |
324 android_manifest = entry.Gradle().get('android_manifest') | 315 return set(srcjars) |
325 if not android_manifest: | 316 |
326 android_manifest = self._GenCustomManifest(entry) | 317 def AllResZips(self, root_entry): |
327 variables['android_manifest'] = self._Relativize(entry, android_manifest) | 318 res_zips = [] |
| 319 for entry in self._GetEntries(root_entry): |
| 320 res_zips += entry.ResZips() |
| 321 return set(_RebasePath(res_zips)) |
| 322 |
| 323 def GeneratedInputs(self, root_entry): |
| 324 generated_inputs = set(self.AllResZips(root_entry)) |
| 325 generated_inputs.update(self.AllSrcjars(root_entry)) |
| 326 for entry in self._GetEntries(root_entry): |
| 327 generated_inputs.update(entry.GeneratedJavaFiles()) |
| 328 generated_inputs.update(entry.PrebuiltJars()) |
| 329 return set(generated_inputs) |
| 330 |
| 331 def Generate(self, root_entry): |
328 # TODO(agrieve): Add an option to use interface jars and see if that speeds | 332 # TODO(agrieve): Add an option to use interface jars and see if that speeds |
329 # things up at all. | 333 # things up at all. |
330 variables['prebuilts'] = self._Relativize(entry, entry.PrebuiltJars()) | 334 variables = {} |
331 deps = [_ProjectEntry.FromBuildConfigPath(p) | 335 java_dirs, excludes = self._GenJavaDirs(root_entry) |
332 for p in entry.Gradle()['dependent_android_projects']] | 336 java_dirs.sort() |
333 variables['android_project_deps'] = [d.ProjectName() for d in deps] | 337 variables['java_dirs'] = self._Relativize(root_entry, java_dirs) |
334 deps = [_ProjectEntry.FromBuildConfigPath(p) | 338 variables['java_dirs'].append(_SRCJARS_SUBDIR) |
335 for p in entry.Gradle()['dependent_java_projects']] | 339 variables['java_excludes'] = excludes |
336 variables['java_project_deps'] = [d.ProjectName() for d in deps] | 340 variables['jni_libs'] = self._Relativize( |
| 341 root_entry, set(self._GenJniLibs(root_entry))) |
| 342 variables['prebuilts'] = [ |
| 343 p for e in self._GetEntries(root_entry) for p in e.PrebuiltJars()] |
| 344 variables['res_dirs'] = [ |
| 345 p for e in self._GetEntries(root_entry) for p in e.ResDirs()] |
| 346 for entry in self._GetEntries(root_entry): |
| 347 variables['prebuilts'] += entry.PrebuiltJars() |
| 348 variables['res_dirs'] += entry.ResDirs() |
| 349 variables['prebuilts'] = self._Relativize( |
| 350 root_entry, set(variables['prebuilts'])) |
| 351 variables['res_dirs'] = self._Relativize( |
| 352 root_entry, set(variables['res_dirs'])) |
| 353 variables['res_dirs'].append(_RES_SUBDIR) |
| 354 android_manifest = root_entry.Gradle().get('android_manifest') |
| 355 if not android_manifest: |
| 356 android_manifest = self._GenCustomManifest(root_entry) |
| 357 variables['android_manifest'] = self._Relativize( |
| 358 root_entry, android_manifest) |
| 359 if self.split_projects: |
| 360 deps = [_ProjectEntry.FromBuildConfigPath(p) |
| 361 for p in root_entry.Gradle()['dependent_android_projects']] |
| 362 variables['android_project_deps'] = [d.ProjectName() for d in deps] |
| 363 deps = [_ProjectEntry.FromBuildConfigPath(p) |
| 364 for p in root_entry.Gradle()['dependent_java_projects']] |
| 365 variables['java_project_deps'] = [d.ProjectName() for d in deps] |
337 return variables | 366 return variables |
338 | 367 |
339 | 368 |
340 def _ComputeJavaSourceDirs(java_files): | 369 def _ComputeJavaSourceDirs(java_files): |
341 """Returns a dictionary of source dirs with each given files in one.""" | 370 """Returns a dictionary of source dirs with each given files in one.""" |
342 found_roots = {} | 371 found_roots = {} |
343 for path in java_files: | 372 for path in java_files: |
344 path_root = path | 373 path_root = path |
345 # Recognize these tokens as top-level. | 374 # Recognize these tokens as top-level. |
346 while True: | 375 while True: |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
604 'May be repeated.') | 633 'May be repeated.') |
605 parser.add_argument('--project-dir', | 634 parser.add_argument('--project-dir', |
606 help='Root of the output project.', | 635 help='Root of the output project.', |
607 default=os.path.join('$CHROMIUM_OUTPUT_DIR', 'gradle')) | 636 default=os.path.join('$CHROMIUM_OUTPUT_DIR', 'gradle')) |
608 parser.add_argument('--all', | 637 parser.add_argument('--all', |
609 action='store_true', | 638 action='store_true', |
610 help='Generate all java targets (slows down IDE)') | 639 help='Generate all java targets (slows down IDE)') |
611 parser.add_argument('--use-gradle-process-resources', | 640 parser.add_argument('--use-gradle-process-resources', |
612 action='store_true', | 641 action='store_true', |
613 help='Have gradle generate R.java rather than ninja') | 642 help='Have gradle generate R.java rather than ninja') |
| 643 parser.add_argument('--split-projects', |
| 644 action='store_true', |
| 645 help='Split projects by their gn deps rather than ' |
| 646 'combining all the dependencies of each target') |
614 args = parser.parse_args() | 647 args = parser.parse_args() |
615 if args.output_directory: | 648 if args.output_directory: |
616 constants.SetOutputDirectory(args.output_directory) | 649 constants.SetOutputDirectory(args.output_directory) |
617 constants.CheckOutputDirectory() | 650 constants.CheckOutputDirectory() |
618 output_dir = constants.GetOutDirectory() | 651 output_dir = constants.GetOutDirectory() |
619 devil_chromium.Initialize(output_directory=output_dir) | 652 devil_chromium.Initialize(output_directory=output_dir) |
620 run_tests_helper.SetLogLevel(args.verbose_count) | 653 run_tests_helper.SetLogLevel(args.verbose_count) |
621 | 654 |
| 655 # TODO(wnwen): Fix packaging so that gradle resources work in this case. |
| 656 if args.use_gradle_process_resources: |
| 657 assert args.split_projects, ( |
| 658 'Gradle resources does not yet work without --split-projects.') |
| 659 |
622 _gradle_output_dir = os.path.abspath( | 660 _gradle_output_dir = os.path.abspath( |
623 args.project_dir.replace('$CHROMIUM_OUTPUT_DIR', output_dir)) | 661 args.project_dir.replace('$CHROMIUM_OUTPUT_DIR', output_dir)) |
624 jinja_processor = jinja_template.JinjaProcessor(_FILE_DIR) | 662 jinja_processor = jinja_template.JinjaProcessor(_FILE_DIR) |
625 build_vars = _ReadBuildVars(output_dir) | 663 build_vars = _ReadBuildVars(output_dir) |
626 generator = _ProjectContextGenerator(_gradle_output_dir, build_vars, | 664 generator = _ProjectContextGenerator(_gradle_output_dir, build_vars, |
627 args.use_gradle_process_resources, jinja_processor) | 665 args.use_gradle_process_resources, jinja_processor, args.split_projects) |
628 logging.warning('Creating project at: %s', generator.project_dir) | 666 logging.warning('Creating project at: %s', generator.project_dir) |
629 | 667 |
630 if args.all: | 668 if args.all: |
631 # Run GN gen if necessary (faster than running "gn gen" in the no-op case). | 669 # Run GN gen if necessary (faster than running "gn gen" in the no-op case). |
632 _RunNinja(constants.GetOutDirectory(), ['build.ninja']) | 670 _RunNinja(constants.GetOutDirectory(), ['build.ninja']) |
633 # Query ninja for all __build_config targets. | 671 # Query ninja for all __build_config targets. |
634 targets = _QueryForAllGnTargets(output_dir) | 672 targets = _QueryForAllGnTargets(output_dir) |
635 else: | 673 else: |
636 targets = args.targets or _DEFAULT_TARGETS | 674 targets = args.targets or _DEFAULT_TARGETS |
637 targets = [re.sub(r'_test_apk$', '_test_apk__apk', t) for t in targets] | 675 targets = [re.sub(r'_test_apk$', '_test_apk__apk', t) for t in targets] |
638 # TODO(wnwen): Utilize Gradle's test constructs for our junit tests? | 676 # TODO(wnwen): Utilize Gradle's test constructs for our junit tests? |
639 targets = [re.sub(r'_junit_tests$', '_junit_tests__java_binary', t) | 677 targets = [re.sub(r'_junit_tests$', '_junit_tests__java_binary', t) |
640 for t in targets] | 678 for t in targets] |
641 | 679 |
642 main_entries = [_ProjectEntry.FromGnTarget(t) for t in targets] | 680 main_entries = [_ProjectEntry.FromGnTarget(t) for t in targets] |
643 | 681 |
644 logging.warning('Building .build_config files...') | 682 logging.warning('Building .build_config files...') |
645 _RunNinja(output_dir, [e.NinjaBuildConfigTarget() for e in main_entries]) | 683 _RunNinja(output_dir, [e.NinjaBuildConfigTarget() for e in main_entries]) |
646 | 684 |
647 # There are many unused libraries, so restrict to those that are actually used | 685 # There are many unused libraries, so restrict to those that are actually used |
648 # when using --all. | 686 # when using --all. |
649 if args.all: | 687 if args.all: |
650 main_entries = [e for e in main_entries if e.GetType() == 'android_apk'] | 688 main_entries = [e for e in main_entries if e.GetType() == 'android_apk'] |
651 | 689 |
652 all_entries = _FindAllProjectEntries(main_entries) | 690 if args.split_projects: |
653 logging.info('Found %d dependent build_config targets.', len(all_entries)) | 691 main_entries = _FindAllProjectEntries(main_entries) |
654 entries = _CombineTestEntries(all_entries) | 692 logging.info('Found %d dependent build_config targets.', len(main_entries)) |
| 693 entries = _CombineTestEntries(main_entries) |
655 logging.info('Creating %d projects for targets.', len(entries)) | 694 logging.info('Creating %d projects for targets.', len(entries)) |
656 | 695 |
657 logging.warning('Writing .gradle files...') | 696 logging.warning('Writing .gradle files...') |
658 project_entries = [] | 697 project_entries = [] |
659 zip_tuples = [] | 698 zip_tuples = [] |
660 generated_inputs = [] | 699 generated_inputs = [] |
661 for entry in entries: | 700 for entry in entries: |
662 if entry.GetType() not in ('android_apk', 'java_library', 'java_binary'): | 701 if entry.GetType() not in ('android_apk', 'java_library', 'java_binary'): |
663 continue | 702 continue |
664 | 703 |
665 data = _GenerateGradleFile(entry, generator, build_vars, jinja_processor) | 704 data = _GenerateGradleFile(entry, generator, build_vars, jinja_processor) |
666 if data: | 705 if data: |
667 project_entries.append(entry) | 706 project_entries.append(entry) |
668 # Build all paths references by .gradle that exist within output_dir. | 707 # Build all paths references by .gradle that exist within output_dir. |
669 generated_inputs.extend(generator.GeneratedInputs(entry)) | 708 generated_inputs.extend(generator.GeneratedInputs(entry)) |
670 zip_tuples.extend( | 709 zip_tuples.extend( |
671 (s, os.path.join(generator.EntryOutputDir(entry), _SRCJARS_SUBDIR)) | 710 (s, os.path.join(generator.EntryOutputDir(entry), _SRCJARS_SUBDIR)) |
672 for s in generator.Srcjars(entry)) | 711 for s in generator.AllSrcjars(entry)) |
673 zip_tuples.extend( | 712 zip_tuples.extend( |
674 (s, os.path.join(generator.EntryOutputDir(entry), _RES_SUBDIR)) | 713 (s, os.path.join(generator.EntryOutputDir(entry), _RES_SUBDIR)) |
675 for s in _RebasePath(entry.ResZips())) | 714 for s in generator.AllResZips(entry)) |
676 _WriteFile( | 715 _WriteFile( |
677 os.path.join(generator.EntryOutputDir(entry), 'build.gradle'), data) | 716 os.path.join(generator.EntryOutputDir(entry), 'build.gradle'), data) |
678 | 717 |
679 _WriteFile(os.path.join(generator.project_dir, 'build.gradle'), | 718 _WriteFile(os.path.join(generator.project_dir, 'build.gradle'), |
680 _GenerateRootGradle(jinja_processor)) | 719 _GenerateRootGradle(jinja_processor)) |
681 | 720 |
682 _WriteFile(os.path.join(generator.project_dir, 'settings.gradle'), | 721 _WriteFile(os.path.join(generator.project_dir, 'settings.gradle'), |
683 _GenerateSettingsGradle(project_entries)) | 722 _GenerateSettingsGradle(project_entries)) |
684 | 723 |
685 sdk_path = _RebasePath(build_vars['android_sdk_root']) | 724 sdk_path = _RebasePath(build_vars['android_sdk_root']) |
686 _WriteFile(os.path.join(generator.project_dir, 'local.properties'), | 725 _WriteFile(os.path.join(generator.project_dir, 'local.properties'), |
687 _GenerateLocalProperties(sdk_path)) | 726 _GenerateLocalProperties(sdk_path)) |
688 | 727 |
689 if generated_inputs: | 728 if generated_inputs: |
690 logging.warning('Building generated source files...') | 729 logging.warning('Building generated source files...') |
691 targets = _RebasePath(generated_inputs, output_dir) | 730 targets = _RebasePath(generated_inputs, output_dir) |
692 _RunNinja(output_dir, targets) | 731 _RunNinja(output_dir, targets) |
693 | 732 |
694 if zip_tuples: | 733 if zip_tuples: |
695 _ExtractZips(generator.project_dir, zip_tuples) | 734 _ExtractZips(generator.project_dir, zip_tuples) |
696 | 735 |
697 logging.warning('Project created! (%d subprojects)', len(project_entries)) | 736 logging.warning('Project created! (%d subprojects)', len(project_entries)) |
698 logging.warning('Generated projects work best with Android Studio 2.2') | 737 logging.warning('Generated projects work best with Android Studio 2.2') |
699 logging.warning('For more tips: https://chromium.googlesource.com/chromium' | 738 logging.warning('For more tips: https://chromium.googlesource.com/chromium' |
700 '/src.git/+/master/docs/android_studio.md') | 739 '/src.git/+/master/docs/android_studio.md') |
701 | 740 |
702 | 741 |
703 if __name__ == '__main__': | 742 if __name__ == '__main__': |
704 main() | 743 main() |
OLD | NEW |