Chromium Code Reviews| OLD | NEW |
|---|---|
| 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). |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 26 sys.path.insert(1, | 26 sys.path.insert(1, |
| 27 os.path.join(os.path.dirname(__file__), '../../../third_party')) | 27 os.path.join(os.path.dirname(__file__), '../../../third_party')) |
| 28 from jinja2 import Template # pylint: disable=F0401 | 28 from jinja2 import Template # pylint: disable=F0401 |
| 29 | 29 |
| 30 | 30 |
| 31 # Represents a line from a R.txt file. | 31 # Represents a line from a R.txt file. |
| 32 TextSymbolsEntry = collections.namedtuple('RTextEntry', | 32 TextSymbolsEntry = collections.namedtuple('RTextEntry', |
| 33 ('java_type', 'resource_type', 'name', 'value')) | 33 ('java_type', 'resource_type', 'name', 'value')) |
| 34 | 34 |
| 35 | 35 |
| 36 def ParseArgs(args): | 36 def _ParseArgs(args): |
| 37 """Parses command line options. | 37 """Parses command line options. |
| 38 | 38 |
| 39 Returns: | 39 Returns: |
| 40 An options object as from optparse.OptionsParser.parse_args() | 40 An options object as from optparse.OptionsParser.parse_args() |
| 41 """ | 41 """ |
| 42 parser = optparse.OptionParser() | 42 parser = optparse.OptionParser() |
| 43 build_utils.AddDepfileOption(parser) | 43 build_utils.AddDepfileOption(parser) |
| 44 | 44 |
| 45 parser.add_option('--android-sdk', help='path to the Android SDK folder') | 45 parser.add_option('--android-sdk', help='path to the Android SDK folder') |
| 46 parser.add_option('--aapt-path', | 46 parser.add_option('--aapt-path', |
| 47 help='path to the Android aapt tool') | 47 help='path to the Android aapt tool') |
| 48 parser.add_option('--non-constant-id', action='store_true') | 48 parser.add_option('--non-constant-id', action='store_true') |
| 49 | 49 |
| 50 parser.add_option('--android-manifest', help='AndroidManifest.xml path') | 50 parser.add_option('--android-manifest', help='AndroidManifest.xml path') |
| 51 parser.add_option('--custom-package', help='Java package for R.java') | 51 parser.add_option('--custom-package', help='Java package for R.java') |
| 52 parser.add_option( | 52 parser.add_option( |
| 53 '--shared-resources', | 53 '--shared-resources', |
| 54 action='store_true', | 54 action='store_true', |
| 55 help='Make a resource package that can be loaded by a different' | 55 help='Make a resource package that can be loaded by a different' |
| 56 'application at runtime to access the package\'s resources.') | 56 'application at runtime to access the package\'s resources.') |
| 57 parser.add_option( | 57 parser.add_option( |
| 58 '--app-as-shared-lib', | 58 '--app-as-shared-lib', |
|
pkotwicz
2015/09/24 20:00:29
Should app_as_shared_lib be part of input_strings
agrieve
2015/09/24 20:28:14
Done.
| |
| 59 action='store_true', | 59 action='store_true', |
| 60 help='Make a resource package that can be loaded as shared library.') | 60 help='Make a resource package that can be loaded as shared library.') |
| 61 | 61 |
| 62 parser.add_option('--resource-dirs', | 62 parser.add_option('--resource-dirs', |
| 63 help='Directories containing resources of this target.') | 63 help='Directories containing resources of this target.') |
| 64 parser.add_option('--dependencies-res-zips', | 64 parser.add_option('--dependencies-res-zips', |
| 65 help='Resources from dependents.') | 65 help='Resources from dependents.') |
| 66 | 66 |
| 67 parser.add_option('--resource-zip-out', | 67 parser.add_option('--resource-zip-out', |
| 68 help='Path for output zipped resources.') | 68 help='Path for output zipped resources.') |
| 69 | 69 |
| 70 parser.add_option('--R-dir', | 70 parser.add_option('--R-dir', |
| 71 help='directory to hold generated R.java.') | 71 help='directory to hold generated R.java.') |
| 72 parser.add_option('--srcjar-out', | 72 parser.add_option('--srcjar-out', |
| 73 help='Path to srcjar to contain generated R.java.') | 73 help='Path to srcjar to contain generated R.java.') |
| 74 parser.add_option('--r-text-out', | 74 parser.add_option('--r-text-out', |
| 75 help='Path to store the R.txt file generated by appt.') | 75 help='Path to store the R.txt file generated by appt.') |
| 76 | 76 |
| 77 parser.add_option('--proguard-file', | 77 parser.add_option('--proguard-file', |
| 78 help='Path to proguard.txt generated file') | 78 help='Path to proguard.txt generated file') |
| 79 | 79 |
| 80 parser.add_option( | 80 parser.add_option( |
| 81 '--v14-skip', | 81 '--v14-skip', |
|
pkotwicz
2015/09/24 20:00:29
Should v14_skip be part of input_strings ?
agrieve
2015/09/24 20:28:14
Done.
| |
| 82 action="store_true", | 82 action="store_true", |
| 83 help='Do not generate nor verify v14 resources') | 83 help='Do not generate nor verify v14 resources') |
| 84 | 84 |
| 85 parser.add_option( | 85 parser.add_option( |
| 86 '--extra-res-packages', | 86 '--extra-res-packages', |
| 87 default=[], | |
| 87 help='Additional package names to generate R.java files for') | 88 help='Additional package names to generate R.java files for') |
| 88 parser.add_option( | 89 parser.add_option( |
| 89 '--extra-r-text-files', | 90 '--extra-r-text-files', |
| 91 default=[], | |
| 90 help='For each additional package, the R.txt file should contain a ' | 92 help='For each additional package, the R.txt file should contain a ' |
| 91 'list of resources to be included in the R.java file in the format ' | 93 'list of resources to be included in the R.java file in the format ' |
| 92 'generated by aapt') | 94 'generated by aapt') |
| 93 parser.add_option( | 95 parser.add_option( |
| 94 '--include-all-resources', | 96 '--include-all-resources', |
| 95 action='store_true', | 97 action='store_true', |
| 96 help='Include every resource ID in every generated R.java file ' | 98 help='Include every resource ID in every generated R.java file ' |
| 97 '(ignoring R.txt).') | 99 '(ignoring R.txt).') |
| 98 | 100 |
| 99 parser.add_option( | 101 parser.add_option( |
| 100 '--all-resources-zip-out', | 102 '--all-resources-zip-out', |
| 101 help='Path for output of all resources. This includes resources in ' | 103 help='Path for output of all resources. This includes resources in ' |
| 102 'dependencies.') | 104 'dependencies.') |
| 103 | 105 |
| 104 parser.add_option('--stamp', help='File to touch on success') | 106 parser.add_option('--stamp', help='File to touch on success') |
| 105 | 107 |
| 106 (options, args) = parser.parse_args(args) | 108 options, positional_args = parser.parse_args(args) |
| 107 | 109 |
| 108 if args: | 110 if positional_args: |
| 109 parser.error('No positional arguments should be given.') | 111 parser.error('No positional arguments should be given.') |
| 110 | 112 |
| 111 # Check that required options have been provided. | 113 # Check that required options have been provided. |
| 112 required_options = ( | 114 required_options = ( |
| 113 'android_sdk', | 115 'android_sdk', |
| 114 'aapt_path', | 116 'aapt_path', |
| 115 'android_manifest', | 117 'android_manifest', |
| 116 'dependencies_res_zips', | 118 'dependencies_res_zips', |
| 117 'resource_dirs', | 119 'resource_dirs', |
| 118 'resource_zip_out', | 120 'resource_zip_out', |
| 119 ) | 121 ) |
| 120 build_utils.CheckOptions(options, parser, required=required_options) | 122 build_utils.CheckOptions(options, parser, required=required_options) |
| 121 | 123 |
| 122 if (options.R_dir is None) == (options.srcjar_out is None): | 124 if (options.R_dir is None) == (options.srcjar_out is None): |
| 123 raise Exception('Exactly one of --R-dir or --srcjar-out must be specified.') | 125 raise Exception('Exactly one of --R-dir or --srcjar-out must be specified.') |
| 124 | 126 |
| 127 options.resource_dirs = build_utils.ParseGypList(options.resource_dirs) | |
| 128 options.dependencies_res_zips = ( | |
| 129 build_utils.ParseGypList(options.dependencies_res_zips)) | |
| 130 if options.extra_res_packages: | |
| 131 options.extra_res_packages = ( | |
| 132 build_utils.ParseGypList(options.extra_res_packages)) | |
| 133 if options.extra_r_text_files: | |
| 134 options.extra_r_text_files = ( | |
| 135 build_utils.ParseGypList(options.extra_r_text_files)) | |
| 136 | |
| 125 return options | 137 return options |
| 126 | 138 |
| 127 | 139 |
| 128 def CreateExtraRJavaFiles( | 140 def CreateExtraRJavaFiles( |
| 129 r_dir, extra_packages, extra_r_text_files, shared_resources, include_all): | 141 r_dir, extra_packages, extra_r_text_files, shared_resources, include_all): |
| 130 if include_all: | 142 if include_all: |
| 131 java_files = build_utils.FindInDirectory(r_dir, "R.java") | 143 java_files = build_utils.FindInDirectory(r_dir, "R.java") |
| 132 if len(java_files) != 1: | 144 if len(java_files) != 1: |
| 133 return | 145 return |
| 134 r_java_file = java_files[0] | 146 r_java_file = java_files[0] |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 316 # of the form 0, 1, ..., then each subdirectory will be passed to aapt as a | 328 # of the form 0, 1, ..., then each subdirectory will be passed to aapt as a |
| 317 # resources directory. While some resources just clobber others (image files, | 329 # resources directory. While some resources just clobber others (image files, |
| 318 # etc), other resources (particularly .xml files) need to be more | 330 # etc), other resources (particularly .xml files) need to be more |
| 319 # intelligently merged. That merging is left up to aapt. | 331 # intelligently merged. That merging is left up to aapt. |
| 320 def path_transform(name, src_zip): | 332 def path_transform(name, src_zip): |
| 321 return '%d/%s' % (zip_files.index(src_zip), name) | 333 return '%d/%s' % (zip_files.index(src_zip), name) |
| 322 | 334 |
| 323 build_utils.MergeZips(output_path, zip_files, path_transform=path_transform) | 335 build_utils.MergeZips(output_path, zip_files, path_transform=path_transform) |
| 324 | 336 |
| 325 | 337 |
| 326 def main(): | 338 def _OnStaleMd5(options): |
| 327 args = build_utils.ExpandFileArgs(sys.argv[1:]) | |
| 328 | |
| 329 options = ParseArgs(args) | |
| 330 android_jar = os.path.join(options.android_sdk, 'android.jar') | 339 android_jar = os.path.join(options.android_sdk, 'android.jar') |
| 331 aapt = options.aapt_path | 340 aapt = options.aapt_path |
| 332 | |
| 333 input_files = [] | |
| 334 | |
| 335 with build_utils.TempDir() as temp_dir: | 341 with build_utils.TempDir() as temp_dir: |
| 336 deps_dir = os.path.join(temp_dir, 'deps') | 342 deps_dir = os.path.join(temp_dir, 'deps') |
| 337 build_utils.MakeDirectory(deps_dir) | 343 build_utils.MakeDirectory(deps_dir) |
| 338 v14_dir = os.path.join(temp_dir, 'v14') | 344 v14_dir = os.path.join(temp_dir, 'v14') |
| 339 build_utils.MakeDirectory(v14_dir) | 345 build_utils.MakeDirectory(v14_dir) |
| 340 | 346 |
| 341 gen_dir = os.path.join(temp_dir, 'gen') | 347 gen_dir = os.path.join(temp_dir, 'gen') |
| 342 build_utils.MakeDirectory(gen_dir) | 348 build_utils.MakeDirectory(gen_dir) |
| 343 | 349 |
| 344 input_resource_dirs = build_utils.ParseGypList(options.resource_dirs) | 350 input_resource_dirs = options.resource_dirs |
| 345 | 351 |
| 346 if not options.v14_skip: | 352 if not options.v14_skip: |
| 347 for resource_dir in input_resource_dirs: | 353 for resource_dir in input_resource_dirs: |
| 348 generate_v14_compatible_resources.GenerateV14Resources( | 354 generate_v14_compatible_resources.GenerateV14Resources( |
| 349 resource_dir, | 355 resource_dir, |
| 350 v14_dir) | 356 v14_dir) |
| 351 | 357 |
| 352 dep_zips = build_utils.ParseGypList(options.dependencies_res_zips) | 358 dep_zips = options.dependencies_res_zips |
| 353 input_files += dep_zips | |
| 354 dep_subdirs = [] | 359 dep_subdirs = [] |
| 355 for z in dep_zips: | 360 for z in dep_zips: |
| 356 subdir = os.path.join(deps_dir, os.path.basename(z)) | 361 subdir = os.path.join(deps_dir, os.path.basename(z)) |
| 357 if os.path.exists(subdir): | 362 if os.path.exists(subdir): |
| 358 raise Exception('Resource zip name conflict: ' + os.path.basename(z)) | 363 raise Exception('Resource zip name conflict: ' + os.path.basename(z)) |
| 359 build_utils.ExtractAll(z, path=subdir) | 364 build_utils.ExtractAll(z, path=subdir) |
| 360 dep_subdirs.append(subdir) | 365 dep_subdirs.append(subdir) |
| 361 | 366 |
| 362 # Generate R.java. This R.java contains non-final constants and is used only | 367 # Generate R.java. This R.java contains non-final constants and is used only |
| 363 # while compiling the library jar (e.g. chromium_content.jar). When building | 368 # while compiling the library jar (e.g. chromium_content.jar). When building |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 388 package_command += ['-G', options.proguard_file] | 393 package_command += ['-G', options.proguard_file] |
| 389 if options.shared_resources: | 394 if options.shared_resources: |
| 390 package_command.append('--shared-lib') | 395 package_command.append('--shared-lib') |
| 391 if options.app_as_shared_lib: | 396 if options.app_as_shared_lib: |
| 392 package_command.append('--app-as-shared-lib') | 397 package_command.append('--app-as-shared-lib') |
| 393 build_utils.CheckOutput(package_command, print_stderr=False) | 398 build_utils.CheckOutput(package_command, print_stderr=False) |
| 394 | 399 |
| 395 if options.extra_res_packages: | 400 if options.extra_res_packages: |
| 396 CreateExtraRJavaFiles( | 401 CreateExtraRJavaFiles( |
| 397 gen_dir, | 402 gen_dir, |
| 398 build_utils.ParseGypList(options.extra_res_packages), | 403 options.extra_res_packages, |
| 399 build_utils.ParseGypList(options.extra_r_text_files), | 404 options.extra_r_text_files, |
| 400 options.shared_resources, | 405 options.shared_resources, |
| 401 options.include_all_resources) | 406 options.include_all_resources) |
| 402 | 407 |
| 403 # This is the list of directories with resources to put in the final .zip | 408 # This is the list of directories with resources to put in the final .zip |
| 404 # file. The order of these is important so that crunched/v14 resources | 409 # file. The order of these is important so that crunched/v14 resources |
| 405 # override the normal ones. | 410 # override the normal ones. |
| 406 zip_resource_dirs = input_resource_dirs + [v14_dir] | 411 zip_resource_dirs = input_resource_dirs + [v14_dir] |
| 407 | 412 |
| 408 base_crunch_dir = os.path.join(temp_dir, 'crunch') | 413 base_crunch_dir = os.path.join(temp_dir, 'crunch') |
| 409 | 414 |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 428 else: | 433 else: |
| 429 build_utils.ZipDir(options.srcjar_out, gen_dir) | 434 build_utils.ZipDir(options.srcjar_out, gen_dir) |
| 430 | 435 |
| 431 if options.r_text_out: | 436 if options.r_text_out: |
| 432 r_text_path = os.path.join(gen_dir, 'R.txt') | 437 r_text_path = os.path.join(gen_dir, 'R.txt') |
| 433 if os.path.exists(r_text_path): | 438 if os.path.exists(r_text_path): |
| 434 shutil.copyfile(r_text_path, options.r_text_out) | 439 shutil.copyfile(r_text_path, options.r_text_out) |
| 435 else: | 440 else: |
| 436 open(options.r_text_out, 'w').close() | 441 open(options.r_text_out, 'w').close() |
| 437 | 442 |
| 438 if options.depfile: | |
| 439 input_files += build_utils.GetPythonDependencies() | |
| 440 build_utils.WriteDepfile(options.depfile, input_files) | |
| 441 | 443 |
| 442 if options.stamp: | 444 def main(args): |
| 443 build_utils.Touch(options.stamp) | 445 args = build_utils.ExpandFileArgs(args) |
| 446 options = _ParseArgs(args) | |
| 447 | |
| 448 possible_output_paths = [ | |
| 449 options.resource_zip_out, | |
| 450 options.all_resources_zip_out, | |
| 451 options.r_text_out, | |
| 452 options.srcjar_out, | |
| 453 ] | |
| 454 output_paths = [x for x in possible_output_paths if x] | |
| 455 | |
| 456 # List python deps in input_strings rather than input_paths since the contents | |
| 457 # of them does not change what gets written to the depsfile. | |
| 458 input_strings = options.extra_res_packages + [ | |
| 459 options.android_sdk, | |
| 460 options.aapt_path, | |
| 461 options.include_all_resources, | |
| 462 options.shared_resources, | |
| 463 options.custom_package, | |
| 464 options.non_constant_id, | |
| 465 ] | |
| 466 | |
| 467 input_paths = [ options.android_manifest ] | |
| 468 input_paths.extend(options.dependencies_res_zips) | |
| 469 input_paths.extend(options.extra_r_text_files) | |
| 470 | |
| 471 if options.proguard_file: | |
| 472 input_paths.append(options.proguard_file) | |
| 473 | |
| 474 for d in options.resource_dirs: | |
| 475 for root, _, filenames in os.walk(d): | |
| 476 input_paths.extend(os.path.join(root, f) for f in filenames) | |
| 477 | |
| 478 build_utils.CallAndWriteDepfileIfStale( | |
| 479 lambda: _OnStaleMd5(options), | |
| 480 options, | |
| 481 input_paths=input_paths, | |
| 482 input_strings=input_strings, | |
| 483 output_paths=output_paths, | |
| 484 # TODO(agrieve): Remove R_dir when it's no longer used (used only by GYP). | |
| 485 force=options.R_dir) | |
| 444 | 486 |
| 445 | 487 |
| 446 if __name__ == '__main__': | 488 if __name__ == '__main__': |
| 447 main() | 489 main(sys.argv[1:]) |
| OLD | NEW |