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

Side by Side Diff: build/android/gyp/process_resources.py

Issue 2090543002: Revert of 🎂 Refactor process_resources.py to use aapt's --extra-packages (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 6 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 | « no previous file | no next file » | 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 # 2 #
3 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 3 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be 4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file. 5 # found in the LICENSE file.
6 6
7 """Process Android resources to generate R.java, and prepare for packaging. 7 """Process Android resources to generate R.java, and prepare for packaging.
8 8
9 This will crunch images and generate v14 compatible resources 9 This will crunch images and generate v14 compatible resources
10 (see generate_v14_compatible_resources.py). 10 (see generate_v14_compatible_resources.py).
11 """ 11 """
12 12
13 import codecs 13 import codecs
14 import collections 14 import collections
15 import optparse 15 import optparse
16 import os 16 import os
17 import re 17 import re
18 import shutil 18 import shutil
19 import sys 19 import sys
20 import xml.etree.ElementTree
21 20
22 import generate_v14_compatible_resources 21 import generate_v14_compatible_resources
23 22
24 from util import build_utils 23 from util import build_utils
25 24
26 # Import jinja2 from third_party/jinja2 25 # Import jinja2 from third_party/jinja2
27 sys.path.insert(1, 26 sys.path.insert(1,
28 os.path.join(os.path.dirname(__file__), '../../../third_party')) 27 os.path.join(os.path.dirname(__file__), '../../../third_party'))
29 from jinja2 import Template # pylint: disable=F0401 28 from jinja2 import Template # pylint: disable=F0401
30 29
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 136
138 if options.extra_r_text_files: 137 if options.extra_r_text_files:
139 options.extra_r_text_files = ( 138 options.extra_r_text_files = (
140 build_utils.ParseGypList(options.extra_r_text_files)) 139 build_utils.ParseGypList(options.extra_r_text_files))
141 else: 140 else:
142 options.extra_r_text_files = [] 141 options.extra_r_text_files = []
143 142
144 return options 143 return options
145 144
146 145
147 def CreateRJavaFiles(srcjar_dir, main_r_txt_file, packages, r_txt_files, 146 def CreateExtraRJavaFiles(
148 shared_resources): 147 r_dir, extra_packages, extra_r_text_files, shared_resources, include_all):
149 assert len(packages) == len(r_txt_files), 'Need one R.txt file per package' 148 if include_all:
149 java_files = build_utils.FindInDirectory(r_dir, "R.java")
150 if len(java_files) != 1:
151 return
152 r_java_file = java_files[0]
153 r_java_contents = codecs.open(r_java_file, encoding='utf-8').read()
150 154
151 # Map of (resource_type, name) -> Entry. 155 for package in extra_packages:
152 # Contains the correct values for resources. 156 package_r_java_dir = os.path.join(r_dir, *package.split('.'))
153 all_resources = {} 157 build_utils.MakeDirectory(package_r_java_dir)
154 for entry in _ParseTextSymbolsFile(main_r_txt_file): 158 package_r_java_path = os.path.join(package_r_java_dir, 'R.java')
155 all_resources[(entry.resource_type, entry.name)] = entry 159 new_r_java = re.sub(r'package [.\w]*;', u'package %s;' % package,
160 r_java_contents)
161 codecs.open(package_r_java_path, 'w', encoding='utf-8').write(new_r_java)
162 else:
163 if len(extra_packages) != len(extra_r_text_files):
164 raise Exception('Need one R.txt file per extra package')
156 165
157 # Map of package_name->resource_type->entry 166 r_txt_file = os.path.join(r_dir, 'R.txt')
158 resources_by_package = ( 167 if not os.path.exists(r_txt_file):
159 collections.defaultdict(lambda: collections.defaultdict(list))) 168 return
160 # Build the R.java files using each package's R.txt file, but replacing 169
161 # each entry's placeholder value with correct values from all_resources. 170 # Map of (resource_type, name) -> Entry.
162 for package, r_txt_file in zip(packages, r_txt_files): 171 # Contains the correct values for resources.
163 if package in resources_by_package: 172 all_resources = {}
164 raise Exception(('Package name "%s" appeared twice. All '
165 'android_resources() targets must use unique package '
166 'names, or no package name at all.') % package)
167 resources_by_type = resources_by_package[package]
168 # The sub-R.txt files have the wrong values at this point. Read them to
169 # figure out which entries belong to them, but use the values from the
170 # main R.txt file.
171 for entry in _ParseTextSymbolsFile(r_txt_file): 173 for entry in _ParseTextSymbolsFile(r_txt_file):
172 entry = all_resources[(entry.resource_type, entry.name)] 174 all_resources[(entry.resource_type, entry.name)] = entry
173 resources_by_type[entry.resource_type].append(entry)
174 175
175 for package, resources_by_type in resources_by_package.iteritems(): 176 # Map of package_name->resource_type->entry
176 package_r_java_dir = os.path.join(srcjar_dir, *package.split('.')) 177 resources_by_package = (
177 build_utils.MakeDirectory(package_r_java_dir) 178 collections.defaultdict(lambda: collections.defaultdict(list)))
178 package_r_java_path = os.path.join(package_r_java_dir, 'R.java') 179 # Build the R.java files using each package's R.txt file, but replacing
179 java_file_contents = _CreateExtraRJavaFile( 180 # each entry's placeholder value with correct values from all_resources.
180 package, resources_by_type, shared_resources) 181 for package, r_text_file in zip(extra_packages, extra_r_text_files):
181 with open(package_r_java_path, 'w') as f: 182 if not os.path.exists(r_text_file):
182 f.write(java_file_contents) 183 continue
184 if package in resources_by_package:
185 raise Exception(('Package name "%s" appeared twice. All '
186 'android_resources() targets must use unique package '
187 'names, or no package name at all.') % package)
188 resources_by_type = resources_by_package[package]
189 # The sub-R.txt files have the wrong values at this point. Read them to
190 # figure out which entries belong to them, but use the values from the
191 # main R.txt file.
192 for entry in _ParseTextSymbolsFile(r_text_file):
193 entry = all_resources[(entry.resource_type, entry.name)]
194 resources_by_type[entry.resource_type].append(entry)
195
196 for package, resources_by_type in resources_by_package.iteritems():
197 package_r_java_dir = os.path.join(r_dir, *package.split('.'))
198 build_utils.MakeDirectory(package_r_java_dir)
199 package_r_java_path = os.path.join(package_r_java_dir, 'R.java')
200 java_file_contents = _CreateExtraRJavaFile(
201 package, resources_by_type, shared_resources)
202 with open(package_r_java_path, 'w') as f:
203 f.write(java_file_contents)
183 204
184 205
185 def _ParseTextSymbolsFile(path): 206 def _ParseTextSymbolsFile(path):
186 """Given an R.txt file, returns a list of TextSymbolsEntry.""" 207 """Given an R.txt file, returns a list of TextSymbolsEntry."""
187 ret = [] 208 ret = []
188 with open(path) as f: 209 with open(path) as f:
189 for line in f: 210 for line in f:
190 m = re.match(r'(int(?:\[\])?) (\w+) (\w+) (.+)$', line) 211 m = re.match(r'(int(?:\[\])?) (\w+) (\w+) (.+)$', line)
191 if not m: 212 if not m:
192 raise Exception('Unexpected line in R.txt: %s' % line) 213 raise Exception('Unexpected line in R.txt: %s' % line)
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 # of the form 0, 1, ..., then each subdirectory will be passed to aapt as a 334 # of the form 0, 1, ..., then each subdirectory will be passed to aapt as a
314 # resources directory. While some resources just clobber others (image files, 335 # resources directory. While some resources just clobber others (image files,
315 # etc), other resources (particularly .xml files) need to be more 336 # etc), other resources (particularly .xml files) need to be more
316 # intelligently merged. That merging is left up to aapt. 337 # intelligently merged. That merging is left up to aapt.
317 def path_transform(name, src_zip): 338 def path_transform(name, src_zip):
318 return '%d/%s' % (zip_files.index(src_zip), name) 339 return '%d/%s' % (zip_files.index(src_zip), name)
319 340
320 build_utils.MergeZips(output_path, zip_files, path_transform=path_transform) 341 build_utils.MergeZips(output_path, zip_files, path_transform=path_transform)
321 342
322 343
323 def _ExtractPackageFromManifest(manifest_path):
324 doc = xml.etree.ElementTree.parse(manifest_path)
325 return doc.getroot().get('package')
326
327
328 def _OnStaleMd5(options): 344 def _OnStaleMd5(options):
329 aapt = options.aapt_path 345 aapt = options.aapt_path
330 with build_utils.TempDir() as temp_dir: 346 with build_utils.TempDir() as temp_dir:
331 deps_dir = os.path.join(temp_dir, 'deps') 347 deps_dir = os.path.join(temp_dir, 'deps')
332 build_utils.MakeDirectory(deps_dir) 348 build_utils.MakeDirectory(deps_dir)
333 v14_dir = os.path.join(temp_dir, 'v14') 349 v14_dir = os.path.join(temp_dir, 'v14')
334 build_utils.MakeDirectory(v14_dir) 350 build_utils.MakeDirectory(v14_dir)
335 351
336 gen_dir = os.path.join(temp_dir, 'gen') 352 gen_dir = os.path.join(temp_dir, 'gen')
337 build_utils.MakeDirectory(gen_dir) 353 build_utils.MakeDirectory(gen_dir)
338 r_txt_path = os.path.join(gen_dir, 'R.txt')
339 srcjar_dir = os.path.join(temp_dir, 'java')
340 354
341 input_resource_dirs = options.resource_dirs 355 input_resource_dirs = options.resource_dirs
342 356
343 if not options.v14_skip: 357 if not options.v14_skip:
344 for resource_dir in input_resource_dirs: 358 for resource_dir in input_resource_dirs:
345 generate_v14_compatible_resources.GenerateV14Resources( 359 generate_v14_compatible_resources.GenerateV14Resources(
346 resource_dir, 360 resource_dir,
347 v14_dir) 361 v14_dir)
348 362
349 dep_zips = options.dependencies_res_zips 363 dep_zips = options.dependencies_res_zips
(...skipping 11 matching lines...) Expand all
361 # generated by merging the resources from all libraries and the main apk 375 # generated by merging the resources from all libraries and the main apk
362 # project. 376 # project.
363 package_command = [aapt, 377 package_command = [aapt,
364 'package', 378 'package',
365 '-m', 379 '-m',
366 '-M', options.android_manifest, 380 '-M', options.android_manifest,
367 '--auto-add-overlay', 381 '--auto-add-overlay',
368 '--no-version-vectors', 382 '--no-version-vectors',
369 '-I', options.android_sdk_jar, 383 '-I', options.android_sdk_jar,
370 '--output-text-symbols', gen_dir, 384 '--output-text-symbols', gen_dir,
371 '-J', gen_dir, # Required for R.txt generation. 385 '-J', gen_dir,
372 '--ignore-assets', build_utils.AAPT_IGNORE_PATTERN] 386 '--ignore-assets', build_utils.AAPT_IGNORE_PATTERN]
373 387
374 # aapt supports only the "--include-all-resources" mode, where each R.java
375 # file ends up with all symbols, rather than only those that it had at the
376 # time it was originally generated. This subtle difference makes no
377 # difference when compiling, but can lead to increased unused symbols in the
378 # resulting R.class files.
379 # TODO(agrieve): See if proguard makes this difference actually translate
380 # into a size difference. If not, we can delete all of our custom R.java
381 # template code above (and make include_all_resources the default).
382 if options.include_all_resources:
383 srcjar_dir = gen_dir
384 if options.extra_res_packages:
385 colon_separated = ':'.join(options.extra_res_packages)
386 package_command += ['--extra-packages', colon_separated]
387 if options.non_constant_id:
388 package_command.append('--non-constant-id')
389 if options.custom_package:
390 package_command += ['--custom-package', options.custom_package]
391 if options.shared_resources:
392 package_command.append('--shared-lib')
393 if options.app_as_shared_lib:
394 package_command.append('--app-as-shared-lib')
395
396 for d in input_resource_dirs: 388 for d in input_resource_dirs:
397 package_command += ['-S', d] 389 package_command += ['-S', d]
398 390
399 # Adding all dependencies as sources is necessary for @type/foo references
400 # to symbols within dependencies to resolve. However, it has the side-effect
401 # that all Java symbols from dependencies are copied into the new R.java.
402 # E.g.: It enables an arguably incorrect usage of
403 # "mypackage.R.id.lib_symbol" where "libpackage.R.id.lib_symbol" would be
404 # more correct. This is just how Android works.
405 for d in dep_subdirs: 391 for d in dep_subdirs:
406 package_command += ['-S', d] 392 package_command += ['-S', d]
407 393
394 if options.non_constant_id:
395 package_command.append('--non-constant-id')
396 if options.custom_package:
397 package_command += ['--custom-package', options.custom_package]
408 if options.proguard_file: 398 if options.proguard_file:
409 package_command += ['-G', options.proguard_file] 399 package_command += ['-G', options.proguard_file]
400 if options.shared_resources:
401 package_command.append('--shared-lib')
402 if options.app_as_shared_lib:
403 package_command.append('--app-as-shared-lib')
410 build_utils.CheckOutput(package_command, print_stderr=False) 404 build_utils.CheckOutput(package_command, print_stderr=False)
411 405
412 # When an empty res/ directory is passed, aapt does not write an R.txt. 406 if options.extra_res_packages:
413 if not os.path.exists(r_txt_path): 407 CreateExtraRJavaFiles(
414 build_utils.Touch(r_txt_path) 408 gen_dir,
415 409 options.extra_res_packages,
416 if not options.include_all_resources: 410 options.extra_r_text_files,
417 packages = list(options.extra_res_packages) 411 options.shared_resources or options.app_as_shared_lib,
418 r_txt_files = list(options.extra_r_text_files) 412 options.include_all_resources)
419
420 cur_package = options.custom_package
421 if not options.custom_package:
422 cur_package = _ExtractPackageFromManifest(options.android_manifest)
423
424 # Don't create a .java file for the current resource target when:
425 # - no package name was provided (either by manifest or build rules),
426 # - there was already a dependent android_resources() with the same
427 # package (occurs mostly when an apk target and resources target share
428 # an AndroidManifest.xml)
429 if cur_package != 'dummy.package' and cur_package not in packages:
430 packages.append(cur_package)
431 r_txt_files.append(r_txt_path)
432
433 if packages:
434 shared_resources = options.shared_resources or options.app_as_shared_lib
435 CreateRJavaFiles(srcjar_dir, r_txt_path, packages, r_txt_files,
436 shared_resources)
437 413
438 # This is the list of directories with resources to put in the final .zip 414 # This is the list of directories with resources to put in the final .zip
439 # file. The order of these is important so that crunched/v14 resources 415 # file. The order of these is important so that crunched/v14 resources
440 # override the normal ones. 416 # override the normal ones.
441 zip_resource_dirs = input_resource_dirs + [v14_dir] 417 zip_resource_dirs = input_resource_dirs + [v14_dir]
442 418
443 base_crunch_dir = os.path.join(temp_dir, 'crunch') 419 base_crunch_dir = os.path.join(temp_dir, 'crunch')
444 420
445 # Crunch image resources. This shrinks png files and is necessary for 421 # Crunch image resources. This shrinks png files and is necessary for
446 # 9-patch images to display correctly. 'aapt crunch' accepts only a single 422 # 9-patch images to display correctly. 'aapt crunch' accepts only a single
447 # directory at a time and deletes everything in the output directory. 423 # directory at a time and deletes everything in the output directory.
448 for idx, input_dir in enumerate(input_resource_dirs): 424 for idx, input_dir in enumerate(input_resource_dirs):
449 crunch_dir = os.path.join(base_crunch_dir, str(idx)) 425 crunch_dir = os.path.join(base_crunch_dir, str(idx))
450 build_utils.MakeDirectory(crunch_dir) 426 build_utils.MakeDirectory(crunch_dir)
451 zip_resource_dirs.append(crunch_dir) 427 zip_resource_dirs.append(crunch_dir)
452 CrunchDirectory(aapt, input_dir, crunch_dir) 428 CrunchDirectory(aapt, input_dir, crunch_dir)
453 429
454 ZipResources(zip_resource_dirs, options.resource_zip_out) 430 ZipResources(zip_resource_dirs, options.resource_zip_out)
455 431
456 if options.all_resources_zip_out: 432 if options.all_resources_zip_out:
457 CombineZips([options.resource_zip_out] + dep_zips, 433 CombineZips([options.resource_zip_out] + dep_zips,
458 options.all_resources_zip_out) 434 options.all_resources_zip_out)
459 435
460 if options.R_dir: 436 if options.R_dir:
461 build_utils.DeleteDirectory(options.R_dir) 437 build_utils.DeleteDirectory(options.R_dir)
462 shutil.copytree(srcjar_dir, options.R_dir) 438 shutil.copytree(gen_dir, options.R_dir)
463 else: 439 else:
464 build_utils.ZipDir(options.srcjar_out, srcjar_dir) 440 build_utils.ZipDir(options.srcjar_out, gen_dir)
465 441
466 if options.r_text_out: 442 if options.r_text_out:
467 shutil.copyfile(r_txt_path, options.r_text_out) 443 r_text_path = os.path.join(gen_dir, 'R.txt')
444 if os.path.exists(r_text_path):
445 shutil.copyfile(r_text_path, options.r_text_out)
446 else:
447 open(options.r_text_out, 'w').close()
468 448
469 449
470 def main(args): 450 def main(args):
471 args = build_utils.ExpandFileArgs(args) 451 args = build_utils.ExpandFileArgs(args)
472 options = _ParseArgs(args) 452 options = _ParseArgs(args)
473 453
474 possible_output_paths = [ 454 possible_output_paths = [
475 options.resource_zip_out, 455 options.resource_zip_out,
476 options.all_resources_zip_out, 456 options.all_resources_zip_out,
477 options.proguard_file, 457 options.proguard_file,
(...skipping 12 matching lines...) Expand all
490 options.shared_resources, 470 options.shared_resources,
491 options.v14_skip, 471 options.v14_skip,
492 ] 472 ]
493 473
494 input_paths = [ 474 input_paths = [
495 options.aapt_path, 475 options.aapt_path,
496 options.android_manifest, 476 options.android_manifest,
497 options.android_sdk_jar, 477 options.android_sdk_jar,
498 ] 478 ]
499 input_paths.extend(options.dependencies_res_zips) 479 input_paths.extend(options.dependencies_res_zips)
500 input_paths.extend(options.extra_r_text_files) 480 input_paths.extend(p for p in options.extra_r_text_files if os.path.exists(p))
501 481
502 resource_names = [] 482 resource_names = []
503 for resource_dir in options.resource_dirs: 483 for resource_dir in options.resource_dirs:
504 for resource_file in build_utils.FindInDirectory(resource_dir, '*'): 484 for resource_file in build_utils.FindInDirectory(resource_dir, '*'):
505 input_paths.append(resource_file) 485 input_paths.append(resource_file)
506 resource_names.append(os.path.relpath(resource_file, resource_dir)) 486 resource_names.append(os.path.relpath(resource_file, resource_dir))
507 487
508 # Resource filenames matter to the output, so add them to strings as well. 488 # Resource filenames matter to the output, so add them to strings as well.
509 # This matters if a file is renamed but not changed (http://crbug.com/597126). 489 # This matters if a file is renamed but not changed (http://crbug.com/597126).
510 input_strings.extend(sorted(resource_names)) 490 input_strings.extend(sorted(resource_names))
511 491
512 build_utils.CallAndWriteDepfileIfStale( 492 build_utils.CallAndWriteDepfileIfStale(
513 lambda: _OnStaleMd5(options), 493 lambda: _OnStaleMd5(options),
514 options, 494 options,
515 input_paths=input_paths, 495 input_paths=input_paths,
516 input_strings=input_strings, 496 input_strings=input_strings,
517 output_paths=output_paths, 497 output_paths=output_paths,
518 # TODO(agrieve): Remove R_dir when it's no longer used (used only by GYP). 498 # TODO(agrieve): Remove R_dir when it's no longer used (used only by GYP).
519 force=options.R_dir) 499 force=options.R_dir)
520 500
521 501
522 if __name__ == '__main__': 502 if __name__ == '__main__':
523 main(sys.argv[1:]) 503 main(sys.argv[1:])
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698