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__(self, project_dir, build_vars, use_gradle_process_resources, |
| 202 jinja_processor): |
199 self.project_dir = project_dir | 203 self.project_dir = project_dir |
| 204 self.build_vars = build_vars |
200 self.use_gradle_process_resources = use_gradle_process_resources | 205 self.use_gradle_process_resources = use_gradle_process_resources |
| 206 self.jinja_processor = jinja_processor |
201 | 207 |
202 def _GenJniLibs(self, entry): | 208 def _GenJniLibs(self, entry): |
203 native_section = entry.BuildConfig().get('native') | 209 native_section = entry.BuildConfig().get('native') |
204 if native_section: | 210 if native_section: |
205 jni_libs = _CreateJniLibsDir( | 211 jni_libs = _CreateJniLibsDir( |
206 constants.GetOutDirectory(), self.EntryOutputDir(entry), | 212 constants.GetOutDirectory(), self.EntryOutputDir(entry), |
207 native_section.get('libraries')) | 213 native_section.get('libraries')) |
208 else: | 214 else: |
209 jni_libs = [] | 215 jni_libs = [] |
210 return jni_libs | 216 return jni_libs |
211 | 217 |
212 def _GenJavaDirs(self, entry): | 218 def _GenJavaDirs(self, entry): |
213 java_dirs, excludes = _CreateJavaSourceDir( | 219 java_dirs, excludes = _CreateJavaSourceDir( |
214 constants.GetOutDirectory(), entry.JavaFiles()) | 220 constants.GetOutDirectory(), entry.JavaFiles()) |
215 if self.Srcjars(entry): | 221 if self.Srcjars(entry): |
216 java_dirs.append( | 222 java_dirs.append( |
217 os.path.join(self.EntryOutputDir(entry), _SRCJARS_SUBDIR)) | 223 os.path.join(self.EntryOutputDir(entry), _SRCJARS_SUBDIR)) |
218 return java_dirs, excludes | 224 return java_dirs, excludes |
219 | 225 |
220 def _GenResDirs(self, entry): | 226 def _GenResDirs(self, entry): |
221 res_dirs = list(entry.DepsInfo().get('owned_resources_dirs', [])) | 227 res_dirs = list(entry.DepsInfo().get('owned_resources_dirs', [])) |
222 if entry.ResZips(): | 228 if entry.ResZips(): |
223 res_dirs.append(os.path.join(self.EntryOutputDir(entry), _RES_SUBDIR)) | 229 res_dirs.append(os.path.join(self.EntryOutputDir(entry), _RES_SUBDIR)) |
224 return res_dirs | 230 return res_dirs |
225 | 231 |
| 232 def _GenCustomManifest(self, entry): |
| 233 """Returns the path to the generated AndroidManifest.xml.""" |
| 234 javac = entry.Javac() |
| 235 resource_packages = javac['resource_packages'] |
| 236 output_file = os.path.join( |
| 237 self.EntryOutputDir(entry), 'AndroidManifest.xml') |
| 238 |
| 239 if not resource_packages: |
| 240 logging.error('Target ' + entry.GnTarget() + ' includes resources from ' |
| 241 'unknown package. Unable to process with gradle.') |
| 242 return _DEFAULT_ANDROID_MANIFEST_PATH |
| 243 elif len(resource_packages) > 1: |
| 244 logging.error('Target ' + entry.GnTarget() + ' includes resources from ' |
| 245 'multiple packages. Unable to process with gradle.') |
| 246 return _DEFAULT_ANDROID_MANIFEST_PATH |
| 247 |
| 248 variables = {} |
| 249 variables['compile_sdk_version'] = self.build_vars['android_sdk_version'] |
| 250 variables['package'] = resource_packages[0] |
| 251 |
| 252 data = self.jinja_processor.Render(_TemplatePath('manifest'), variables) |
| 253 _WriteFile(output_file, data) |
| 254 |
| 255 return output_file |
| 256 |
226 def _Relativize(self, entry, paths): | 257 def _Relativize(self, entry, paths): |
227 return _RebasePath(paths, self.EntryOutputDir(entry)) | 258 return _RebasePath(paths, self.EntryOutputDir(entry)) |
228 | 259 |
229 def EntryOutputDir(self, entry): | 260 def EntryOutputDir(self, entry): |
230 return os.path.join(self.project_dir, entry.GradleSubdir()) | 261 return os.path.join(self.project_dir, entry.GradleSubdir()) |
231 | 262 |
232 def Srcjars(self, entry): | 263 def Srcjars(self, entry): |
233 srcjars = _RebasePath(entry.Gradle().get('bundled_srcjars', [])) | 264 srcjars = _RebasePath(entry.Gradle().get('bundled_srcjars', [])) |
234 if not self.use_gradle_process_resources: | 265 if not self.use_gradle_process_resources: |
235 srcjars += _RebasePath(entry.BuildConfig()['javac']['srcjars']) | 266 srcjars += _RebasePath(entry.BuildConfig()['javac']['srcjars']) |
236 return srcjars | 267 return srcjars |
237 | 268 |
238 def GeneratedInputs(self, entry): | 269 def GeneratedInputs(self, entry): |
239 generated_inputs = [] | 270 generated_inputs = [] |
240 generated_inputs.extend(self.Srcjars(entry)) | 271 generated_inputs.extend(self.Srcjars(entry)) |
241 generated_inputs.extend(_RebasePath(entry.ResZips())) | 272 generated_inputs.extend(_RebasePath(entry.ResZips())) |
242 generated_inputs.extend( | 273 generated_inputs.extend( |
243 p for p in entry.JavaFiles() if not p.startswith('..')) | 274 p for p in entry.JavaFiles() if not p.startswith('..')) |
244 generated_inputs.extend(entry.Gradle()['dependent_prebuilt_jars']) | 275 generated_inputs.extend(entry.Gradle()['dependent_prebuilt_jars']) |
245 return generated_inputs | 276 return generated_inputs |
246 | 277 |
247 def Generate(self, entry): | 278 def Generate(self, entry): |
248 variables = {} | 279 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) | 280 java_dirs, excludes = self._GenJavaDirs(entry) |
254 variables['java_dirs'] = self._Relativize(entry, java_dirs) | 281 variables['java_dirs'] = self._Relativize(entry, java_dirs) |
255 variables['java_excludes'] = excludes | 282 variables['java_excludes'] = excludes |
256 variables['jni_libs'] = self._Relativize(entry, self._GenJniLibs(entry)) | 283 variables['jni_libs'] = self._Relativize(entry, self._GenJniLibs(entry)) |
257 variables['res_dirs'] = self._Relativize(entry, self._GenResDirs(entry)) | 284 variables['res_dirs'] = self._Relativize(entry, self._GenResDirs(entry)) |
| 285 android_manifest = entry.Gradle().get('android_manifest') |
| 286 if not android_manifest: |
| 287 # Gradle uses package id from manifest when generating R.class. So, we |
| 288 # need to generate a custom manifest if we let gradle process resources. |
| 289 # We cannot simply set android.defaultConfig.applicationId because it is |
| 290 # not supported for library targets. |
| 291 if variables['res_dirs']: |
| 292 android_manifest = self._GenCustomManifest(entry) |
| 293 else: |
| 294 android_manifest = _DEFAULT_ANDROID_MANIFEST_PATH |
| 295 variables['android_manifest'] = self._Relativize(entry, android_manifest) |
258 deps = [_ProjectEntry.FromBuildConfigPath(p) | 296 deps = [_ProjectEntry.FromBuildConfigPath(p) |
259 for p in entry.Gradle()['dependent_android_projects']] | 297 for p in entry.Gradle()['dependent_android_projects']] |
260 variables['android_project_deps'] = [d.ProjectName() for d in deps] | 298 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 | 299 # TODO(agrieve): Add an option to use interface jars and see if that speeds |
262 # things up at all. | 300 # things up at all. |
263 variables['prebuilts'] = self._Relativize( | 301 variables['prebuilts'] = self._Relativize( |
264 entry, entry.Gradle()['dependent_prebuilt_jars']) | 302 entry, entry.Gradle()['dependent_prebuilt_jars']) |
265 deps = [_ProjectEntry.FromBuildConfigPath(p) | 303 deps = [_ProjectEntry.FromBuildConfigPath(p) |
266 for p in entry.Gradle()['dependent_java_projects']] | 304 for p in entry.Gradle()['dependent_java_projects']] |
267 variables['java_project_deps'] = [d.ProjectName() for d in deps] | 305 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() | 575 args = parser.parse_args() |
538 if args.output_directory: | 576 if args.output_directory: |
539 constants.SetOutputDirectory(args.output_directory) | 577 constants.SetOutputDirectory(args.output_directory) |
540 constants.CheckOutputDirectory() | 578 constants.CheckOutputDirectory() |
541 output_dir = constants.GetOutDirectory() | 579 output_dir = constants.GetOutDirectory() |
542 devil_chromium.Initialize(output_directory=output_dir) | 580 devil_chromium.Initialize(output_directory=output_dir) |
543 run_tests_helper.SetLogLevel(args.verbose_count) | 581 run_tests_helper.SetLogLevel(args.verbose_count) |
544 | 582 |
545 _gradle_output_dir = os.path.abspath( | 583 _gradle_output_dir = os.path.abspath( |
546 args.project_dir.replace('$CHROMIUM_OUTPUT_DIR', output_dir)) | 584 args.project_dir.replace('$CHROMIUM_OUTPUT_DIR', output_dir)) |
547 generator = _ProjectContextGenerator( | 585 jinja_processor = jinja_template.JinjaProcessor(_FILE_DIR) |
548 _gradle_output_dir, args.use_gradle_process_resources) | 586 build_vars = _ReadBuildVars(output_dir) |
| 587 generator = _ProjectContextGenerator(_gradle_output_dir, build_vars, |
| 588 args.use_gradle_process_resources, jinja_processor) |
549 logging.warning('Creating project at: %s', generator.project_dir) | 589 logging.warning('Creating project at: %s', generator.project_dir) |
550 | 590 |
551 if args.all: | 591 if args.all: |
552 # Run GN gen if necessary (faster than running "gn gen" in the no-op case). | 592 # Run GN gen if necessary (faster than running "gn gen" in the no-op case). |
553 _RunNinja(constants.GetOutDirectory(), ['build.ninja']) | 593 _RunNinja(constants.GetOutDirectory(), ['build.ninja']) |
554 # Query ninja for all __build_config targets. | 594 # Query ninja for all __build_config targets. |
555 targets = _QueryForAllGnTargets(output_dir) | 595 targets = _QueryForAllGnTargets(output_dir) |
556 else: | 596 else: |
557 targets = args.targets or _DEFAULT_TARGETS | 597 targets = args.targets or _DEFAULT_TARGETS |
558 targets = [re.sub(r'_test_apk$', '_test_apk__apk', t) for t in targets] | 598 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. | 609 # when using --all. |
570 if args.all: | 610 if args.all: |
571 main_entries = [e for e in main_entries if e.GetType() == 'android_apk'] | 611 main_entries = [e for e in main_entries if e.GetType() == 'android_apk'] |
572 | 612 |
573 all_entries = _FindAllProjectEntries(main_entries) | 613 all_entries = _FindAllProjectEntries(main_entries) |
574 logging.info('Found %d dependent build_config targets.', len(all_entries)) | 614 logging.info('Found %d dependent build_config targets.', len(all_entries)) |
575 entries = _CombineTestEntries(all_entries) | 615 entries = _CombineTestEntries(all_entries) |
576 logging.info('Creating %d projects for targets.', len(entries)) | 616 logging.info('Creating %d projects for targets.', len(entries)) |
577 | 617 |
578 logging.warning('Writing .gradle files...') | 618 logging.warning('Writing .gradle files...') |
579 jinja_processor = jinja_template.JinjaProcessor(_FILE_DIR) | |
580 build_vars = _ReadBuildVars(output_dir) | |
581 project_entries = [] | 619 project_entries = [] |
582 zip_tuples = [] | 620 zip_tuples = [] |
583 generated_inputs = [] | 621 generated_inputs = [] |
584 for entry in entries: | 622 for entry in entries: |
585 if entry.GetType() not in ('android_apk', 'java_library', 'java_binary'): | 623 if entry.GetType() not in ('android_apk', 'java_library', 'java_binary'): |
586 continue | 624 continue |
587 | 625 |
588 data = _GenerateGradleFile(entry, generator, build_vars, jinja_processor) | 626 data = _GenerateGradleFile(entry, generator, build_vars, jinja_processor) |
589 if data: | 627 if data: |
590 project_entries.append(entry) | 628 project_entries.append(entry) |
(...skipping 27 matching lines...) Expand all Loading... |
618 _ExtractZips(generator.project_dir, zip_tuples) | 656 _ExtractZips(generator.project_dir, zip_tuples) |
619 | 657 |
620 logging.warning('Project created! (%d subprojects)', len(project_entries)) | 658 logging.warning('Project created! (%d subprojects)', len(project_entries)) |
621 logging.warning('Generated projects work best with Android Studio 2.2') | 659 logging.warning('Generated projects work best with Android Studio 2.2') |
622 logging.warning('For more tips: https://chromium.googlesource.com/chromium' | 660 logging.warning('For more tips: https://chromium.googlesource.com/chromium' |
623 '/src.git/+/master/docs/android_studio.md') | 661 '/src.git/+/master/docs/android_studio.md') |
624 | 662 |
625 | 663 |
626 if __name__ == '__main__': | 664 if __name__ == '__main__': |
627 main() | 665 main() |
OLD | NEW |