def _ParseOptions(argv): parser = optparse.OptionParser() build_utils.AddDepfileOption(parser) parser.add_option( '--java-srcjars', action='append', default=[], help='List of srcjars to include in compilation.') parser.add_option( '--generated-dir', help='Subdirectory within target_gen_dir to place extracted srcjars and ' 'annotation processor output for codesearch to find.') parser.add_option( '--bootclasspath', action='append', default=[], help='Boot classpath for javac. If this is specified multiple times, ' 'they will all be appended to construct the classpath.') parser.add_option( '--java-version', help='Java language version to use in -source and -target args to javac.') parser.add_option( '--full-classpath', action='append', help='Classpath to use when annotation processors are present.') parser.add_option( '--interface-classpath', action='append', help='Classpath to use when no annotation processors are present.') parser.add_option( '--processors', action='append', help='GN list of annotation processor main classes.') parser.add_option( '--processorpath', action='append', help='GN list of jars that comprise the classpath used for Annotation ' 'Processors.') parser.add_option( '--processor-arg', dest='processor_args', action='append', help='key=value arguments for the annotation processors.') parser.add_option( '--provider-configuration', dest='provider_configurations', action='append', help='File to specify a service provider. Will be included ' 'in the jar under META-INF/services.') parser.add_option( '--additional-jar-file', dest='additional_jar_files', action='append', help='Additional files to package into jar. By default, only Java .class ' 'files are packaged into the jar. Files should be specified in ' 'format <filename>:<path to be placed in jar>.') parser.add_option( '--jar-info-exclude-globs', help='GN list of exclude globs to filter from generated .info files.') parser.add_option( '--chromium-code', type='int', help='Whether code being compiled should be built with stricter ' 'warnings for chromium code.') parser.add_option( '--errorprone-path', help='Use the Errorprone compiler at this path.') parser.add_option( '--enable-errorprone', action='store_true', help='Enable errorprone checks') parser.add_option('--jar-path', help='Jar output path.') parser.add_option( '--javac-arg', action='append', default=[], help='Additional arguments to pass to javac.') options, args = parser.parse_args(argv) build_utils.CheckOptions(options, parser, required=('jar_path',)) options.bootclasspath = build_utils.ParseGnList(options.bootclasspath) options.full_classpath = build_utils.ParseGnList(options.full_classpath) options.interface_classpath = build_utils.ParseGnList( options.interface_classpath) options.processorpath = build_utils.ParseGnList(options.processorpath) options.processors = build_utils.ParseGnList(options.processors) options.java_srcjars = build_utils.ParseGnList(options.java_srcjars) options.jar_info_exclude_globs = build_utils.ParseGnList( options.jar_info_exclude_globs) if options.java_version == '1.8' and options.bootclasspath: # Android's boot jar doesn't contain all java 8 classes. # See: https://github.com/evant/gradle-retrolambda/issues/23. # Get the path of the jdk folder by searching for the 'jar' executable. We # cannot search for the 'javac' executable because goma provides a custom # version of 'javac'. jar_path = os.path.realpath(distutils.spawn.find_executable('jar')) jdk_dir = os.path.dirname(os.path.dirname(jar_path)) rt_jar = os.path.join(jdk_dir, 'jre', 'lib', 'rt.jar') options.bootclasspath.append(rt_jar) additional_jar_files = [] for arg in options.additional_jar_files or []: filepath, jar_filepath = arg.split(':') additional_jar_files.append((filepath, jar_filepath)) options.additional_jar_files = additional_jar_files java_files = [] for arg in args: # Interpret a path prefixed with @ as a file containing a list of sources. if arg.startswith('@'): java_files.extend(build_utils.ReadSourcesList(arg[1:])) else: java_files.append(arg) return options, java_files
def _ParseOptions(): args = build_utils.ExpandFileArgs(sys.argv[1:]) parser = argparse.ArgumentParser() build_utils.AddDepfileOption(parser) parser.add_argument('--r8-path', required=True, help='Path to the R8.jar to use.') parser.add_argument( '--desugar-jdk-libs-json', help='Path to desugar_jdk_libs.json.') parser.add_argument('--input-paths', action='append', required=True, help='GN-list of .jar files to optimize.') parser.add_argument('--desugar-jdk-libs-jar', help='Path to desugar_jdk_libs.jar.') parser.add_argument('--desugar-jdk-libs-configuration-jar', help='Path to desugar_jdk_libs_configuration.jar.') parser.add_argument('--output-path', help='Path to the generated .jar file.') parser.add_argument( '--proguard-configs', action='append', required=True, help='GN-list of configuration files.') parser.add_argument( '--apply-mapping', help='Path to ProGuard mapping to apply.') parser.add_argument( '--mapping-output', required=True, help='Path for ProGuard to output mapping file to.') parser.add_argument( '--extra-mapping-output-paths', help='GN-list of additional paths to copy output mapping file to.') parser.add_argument( '--classpath', action='append', help='GN-list of .jar files to include as libraries.') parser.add_argument( '--main-dex-rules-path', action='append', help='Path to main dex rules for multidex' '- only works with R8.') parser.add_argument( '--min-api', help='Minimum Android API level compatibility.') parser.add_argument( '--verbose', '-v', action='store_true', help='Print all ProGuard output') parser.add_argument( '--repackage-classes', help='Package all optimized classes are put in.') parser.add_argument( '--disable-outlining', action='store_true', help='Disable the outlining optimization provided by R8.') parser.add_argument( '--disable-checkdiscard', action='store_true', help='Disable -checkdiscard directives') parser.add_argument('--sourcefile', help='Value for source file attribute') parser.add_argument( '--force-enable-assertions', action='store_true', help='Forcefully enable javac generated assertion code.') parser.add_argument( '--feature-jars', action='append', help='GN list of path to jars which comprise the corresponding feature.') parser.add_argument( '--dex-dest', action='append', dest='dex_dests', help='Destination for dex file of the corresponding feature.') parser.add_argument( '--feature-name', action='append', dest='feature_names', help='The name of the feature module.') parser.add_argument('--warnings-as-errors', action='store_true', help='Treat all warnings as errors.') parser.add_argument('--show-desugar-default-interface-warnings', action='store_true', help='Enable desugaring warnings.') parser.add_argument( '--stamp', help='File to touch upon success. Mutually exclusive with --output-path') parser.add_argument('--desugared-library-keep-rule-output', help='Path to desugared library keep rule output file.') diff_utils.AddCommandLineFlags(parser) options = parser.parse_args(args) if options.feature_names: if options.output_path: parser.error('Feature splits cannot specify an output in GN.') if not options.actual_file and not options.stamp: parser.error('Feature splits require a stamp file as output.') elif not options.output_path: parser.error('Output path required when feature splits aren\'t used') if options.main_dex_rules_path and not options.r8_path: parser.error('R8 must be enabled to pass main dex rules.') options.classpath = build_utils.ParseGnList(options.classpath) options.proguard_configs = build_utils.ParseGnList(options.proguard_configs) options.input_paths = build_utils.ParseGnList(options.input_paths) options.extra_mapping_output_paths = build_utils.ParseGnList( options.extra_mapping_output_paths) if options.feature_names: if 'base' not in options.feature_names: parser.error('"base" feature required when feature arguments are used.') if len(options.feature_names) != len(options.feature_jars) or len( options.feature_names) != len(options.dex_dests): parser.error('Invalid feature argument lengths.') options.feature_jars = [ build_utils.ParseGnList(x) for x in options.feature_jars ] return options
def _ParseAndFlattenGnLists(gn_lists): ret = [] for arg in gn_lists: ret.extend(build_utils.ParseGnList(arg)) return ret
def _ParseArgs(args): parser = argparse.ArgumentParser() parser.add_argument('--out-bundle', required=True, help='Output bundle zip archive.') parser.add_argument('--module-zips', required=True, help='GN-list of module zip archives.') parser.add_argument('--rtxt-in-paths', action='append', help='GN-list of module R.txt files.') parser.add_argument('--rtxt-out-path', help='Path to combined R.txt file for bundle.') parser.add_argument('--uncompressed-assets', action='append', help='GN-list of uncompressed assets.') parser.add_argument('--uncompress-shared-libraries', action='append', help='Whether to store native libraries uncompressed. ' 'This is a string to allow @FileArg usage.') parser.add_argument('--split-dimensions', help="GN-list of split dimensions to support.") parser.add_argument('--keystore-path', help='Keystore path') parser.add_argument('--keystore-password', help='Keystore password') parser.add_argument('--key-name', help='Keystore key name') options = parser.parse_args(args) options.module_zips = build_utils.ParseGnList(options.module_zips) options.rtxt_in_paths = build_utils.ExpandFileArgs(options.rtxt_in_paths) if len(options.module_zips) == 0: raise Exception('The module zip list cannot be empty.') # Signing is optional, but all --keyXX parameters should be set. if options.keystore_path or options.keystore_password or options.key_name: if not options.keystore_path or not options.keystore_password or \ not options.key_name: raise Exception('When signing the bundle, use --keystore-path, ' '--keystore-password and --key-name.') # Merge all uncompressed assets into a set. uncompressed_list = [] if options.uncompressed_assets: for l in options.uncompressed_assets: for entry in build_utils.ParseGnList(l): # Each entry has the following format: 'zipPath' or 'srcPath:zipPath' pos = entry.find(':') if pos >= 0: uncompressed_list.append(entry[pos + 1:]) else: uncompressed_list.append(entry) options.uncompressed_assets = set(uncompressed_list) # Merge uncompressed native libs flags, they all must have the same value. if options.uncompress_shared_libraries: uncompressed_libs = set(options.uncompress_shared_libraries) if len(uncompressed_libs) > 1: parser.error('Inconsistent uses of --uncompress-native-libs!') options.uncompress_shared_libraries = 'True' in uncompressed_libs # Check that all split dimensions are valid if options.split_dimensions: options.split_dimensions = build_utils.ParseGnList( options.split_dimensions) for dim in options.split_dimensions: if dim.upper() not in _ALL_SPLIT_DIMENSIONS: parser.error( 'Invalid split dimension "%s" (expected one of: %s)' % (dim, ', '.join(x.lower() for x in _ALL_SPLIT_DIMENSIONS))) return options
def _ParseArgs(args): parser = argparse.ArgumentParser() parser.add_argument('--out-bundle', required=True, help='Output bundle zip archive.') parser.add_argument('--module-zips', required=True, help='GN-list of module zip archives.') parser.add_argument( '--pathmap-in-paths', action='append', help='List of module pathmap files.') parser.add_argument( '--module-name', action='append', dest='module_names', help='List of module names.') parser.add_argument( '--pathmap-out-path', help='Path to combined pathmap file for bundle.') parser.add_argument( '--rtxt-in-paths', action='append', help='GN-list of module R.txt files.') parser.add_argument( '--rtxt-out-path', help='Path to combined R.txt file for bundle.') parser.add_argument('--uncompressed-assets', action='append', help='GN-list of uncompressed assets.') parser.add_argument( '--compress-shared-libraries', action='store_true', help='Whether to store native libraries compressed.') parser.add_argument('--split-dimensions', help="GN-list of split dimensions to support.") parser.add_argument( '--base-module-rtxt-path', help='Optional path to the base module\'s R.txt file, only used with ' 'language split dimension.') parser.add_argument( '--base-whitelist-rtxt-path', help='Optional path to an R.txt file, string resources ' 'listed there _and_ in --base-module-rtxt-path will ' 'be kept in the base bundle module, even if language' ' splitting is enabled.') parser.add_argument('--keystore-path', help='Keystore path') parser.add_argument('--keystore-password', help='Keystore password') parser.add_argument('--key-name', help='Keystore key name') options = parser.parse_args(args) options.module_zips = build_utils.ParseGnList(options.module_zips) options.rtxt_in_paths = build_utils.ParseGnList(options.rtxt_in_paths) options.pathmap_in_paths = build_utils.ParseGnList(options.pathmap_in_paths) if len(options.module_zips) == 0: raise Exception('The module zip list cannot be empty.') # Signing is optional, but all --keyXX parameters should be set. if options.keystore_path or options.keystore_password or options.key_name: if not options.keystore_path or not options.keystore_password or \ not options.key_name: raise Exception('When signing the bundle, use --keystore-path, ' '--keystore-password and --key-name.') # Merge all uncompressed assets into a set. uncompressed_list = [] if options.uncompressed_assets: for l in options.uncompressed_assets: for entry in build_utils.ParseGnList(l): # Each entry has the following format: 'zipPath' or 'srcPath:zipPath' pos = entry.find(':') if pos >= 0: uncompressed_list.append(entry[pos + 1:]) else: uncompressed_list.append(entry) options.uncompressed_assets = set(uncompressed_list) # Check that all split dimensions are valid if options.split_dimensions: options.split_dimensions = build_utils.ParseGnList(options.split_dimensions) for dim in options.split_dimensions: if dim.upper() not in _ALL_SPLIT_DIMENSIONS: parser.error('Invalid split dimension "%s" (expected one of: %s)' % ( dim, ', '.join(x.lower() for x in _ALL_SPLIT_DIMENSIONS))) # As a special case, --base-whitelist-rtxt-path can be empty to indicate # that the module doesn't need such a whitelist. That's because it is easier # to check this condition here than through GN rules :-( if options.base_whitelist_rtxt_path == '': options.base_module_rtxt_path = None # Check --base-module-rtxt-path and --base-whitelist-rtxt-path usage. if options.base_module_rtxt_path: if not options.base_whitelist_rtxt_path: parser.error( '--base-module-rtxt-path requires --base-whitelist-rtxt-path') if 'language' not in options.split_dimensions: parser.error('--base-module-rtxt-path is only valid with ' 'language-based splits.') return options
def _ParseOptions(): args = build_utils.ExpandFileArgs(sys.argv[1:]) parser = argparse.ArgumentParser() build_utils.AddDepfileOption(parser) group = parser.add_mutually_exclusive_group(required=True) group.add_argument('--proguard-path', help='Path to the proguard.jar to use.') group.add_argument('--r8-path', help='Path to the R8.jar to use.') parser.add_argument('--input-paths', required=True, help='GN-list of .jar files to optimize.') parser.add_argument('--output-path', required=True, help='Path to the generated .jar file.') parser.add_argument('--proguard-configs', action='append', required=True, help='GN-list of configuration files.') parser.add_argument('--apply-mapping', help='Path to ProGuard mapping to apply.') parser.add_argument('--mapping-output', required=True, help='Path for ProGuard to output mapping file to.') parser.add_argument( '--extra-mapping-output-paths', help='GN-list of additional paths to copy output mapping file to.') parser.add_argument( '--output-config', help='Path to write the merged ProGuard config file to.') parser.add_argument( '--expected-configs-file', help='Path to a file containing the expected merged ProGuard configs') parser.add_argument( '--verify-expected-configs', action='store_true', help='Fail if the expected merged ProGuard configs differ from the ' 'generated merged ProGuard configs.') parser.add_argument('--classpath', action='append', help='GN-list of .jar files to include as libraries.') parser.add_argument('--main-dex-rules-path', action='append', help='Path to main dex rules for multidex' '- only works with R8.') parser.add_argument('--min-api', help='Minimum Android API level compatibility.') parser.add_argument('--verbose', '-v', action='store_true', help='Print all ProGuard output') parser.add_argument( '--repackage-classes', help='Unique package name given to an asynchronously proguarded module' ) parser.add_argument( '--disable-outlining', action='store_true', help='Disable the outlining optimization provided by R8.') options = parser.parse_args(args) if options.main_dex_rules_path and not options.r8_path: parser.error('R8 must be enabled to pass main dex rules.') if options.expected_configs_file and not options.output_config: parser.error('--expected-configs-file requires --output-config') if options.proguard_path and options.disable_outlining: parser.error('--disable-outlining requires --r8-path') options.classpath = build_utils.ParseGnList(options.classpath) options.proguard_configs = build_utils.ParseGnList( options.proguard_configs) options.input_paths = build_utils.ParseGnList(options.input_paths) options.extra_mapping_output_paths = build_utils.ParseGnList( options.extra_mapping_output_paths) if options.apply_mapping: options.apply_mapping = os.path.abspath(options.apply_mapping) return options
def main(): parser = argparse.ArgumentParser() build_utils.AddDepfileOption(parser) parser.add_argument( '--excluded-classes', help='A list of .class file patterns to exclude from the jar.') parser.add_argument('--src-search-dirs', action='append', help='A list of directories that should be searched' ' for the source files.') parser.add_argument('--src-files', action='append', help='A list of source files to jar.') parser.add_argument( '--src-jars', action='append', help='A list of source jars to include in addition to source files.') parser.add_argument('--src-list-files', action='append', help='A list of files that contain a list of sources,' ' e.g. a list of \'.sources\' files generated by GN.') parser.add_argument('--jar-path', help='Jar output path.', required=True) options = parser.parse_args() src_jars = [] for gn_list in options.src_jars: src_jars.extend(build_utils.ParseGnList(gn_list)) src_search_dirs = [] for gn_src_search_dirs in options.src_search_dirs: src_search_dirs.extend(build_utils.ParseGnList(gn_src_search_dirs)) src_list_files = [] if options.src_list_files: for gn_src_list_file in options.src_list_files: src_list_files.extend(build_utils.ParseGnList(gn_src_list_file)) src_files = [] for gn_src_files in options.src_files: src_files.extend(build_utils.ParseGnList(gn_src_files)) # Add files from --source_list_files for src_list_file in src_list_files: with open(src_list_file, 'r') as f: src_files.extend(f.read().splitlines()) # Preprocess source files by removing any prefix that comes before # the Java package name. for i, s in enumerate(src_files): prefix_position = s.find(JAVA_PACKAGE_PREFIX) if prefix_position != -1: src_files[i] = s[prefix_position:] excluded_classes = [] if options.excluded_classes: classes = build_utils.ParseGnList(options.excluded_classes) excluded_classes.extend(f.replace('.class', '.java') for f in classes) predicate = None if excluded_classes: predicate = lambda f: not build_utils.MatchesGlob(f, excluded_classes) # Create a dictionary that maps every source directory # to source files that it contains. dir_to_files_map = {} # Initialize the map. for src_search_dir in src_search_dirs: dir_to_files_map[src_search_dir] = [] # Fill the map. for src_file in src_files: number_of_file_instances = 0 for src_search_dir in src_search_dirs: target_path = os.path.join(src_search_dir, src_file) if os.path.isfile(target_path): number_of_file_instances += 1 if not predicate or predicate(src_file): dir_to_files_map[src_search_dir].append(target_path) if (number_of_file_instances > 1): raise Exception( 'There is more than one instance of file %s in %s' % (src_file, src_search_dirs)) if (number_of_file_instances < 1): raise Exception('Unable to find file %s in %s' % (src_file, src_search_dirs)) # Jar the sources from every source search directory. with build_utils.AtomicOutput(options.jar_path) as o, \ zipfile.ZipFile(o, 'w', zipfile.ZIP_DEFLATED) as z: for src_search_dir in src_search_dirs: subpaths = dir_to_files_map[src_search_dir] if subpaths: build_utils.DoZip(subpaths, z, base_dir=src_search_dir) else: raise Exception( 'Directory %s does not contain any files and can be' ' removed from the list of directories to search' % src_search_dir) # Jar additional src jars if src_jars: build_utils.MergeZips(z, src_jars, compress=True) if options.depfile: deps = [] for sources in dir_to_files_map.itervalues(): deps.extend(sources) # Srcjar deps already captured in GN rules (no need to list them here). build_utils.WriteDepfile(options.depfile, options.jar_path, deps)
def main(): parser = argparse.ArgumentParser() build_utils.AddDepfileOption(parser) parser.add_argument('--lint-path', required=True, help='Path to lint executable.') parser.add_argument('--product-dir', required=True, help='Path to product dir.') parser.add_argument('--result-path', required=True, help='Path to XML lint result file.') parser.add_argument('--cache-dir', required=True, help='Path to the directory in which the android cache ' 'directory tree should be stored.') parser.add_argument('--platform-xml-path', required=True, help='Path to api-platforms.xml') parser.add_argument('--android-sdk-version', help='Version (API level) of the Android SDK used for ' 'building.') parser.add_argument('--can-fail-build', action='store_true', help='If set, script will exit with nonzero exit status' ' if lint errors are present') parser.add_argument('--include-unexpected-failures', action='store_true', help='If set, script will exit with nonzero exit status' ' if lint itself crashes with unexpected failures.') parser.add_argument('--config-path', help='Path to lint suppressions file.') parser.add_argument('--disable', help='List of checks to disable.') parser.add_argument('--jar-path', help='Jar file containing class files.') parser.add_argument('--java-sources-file', help='File containing a list of java files.') parser.add_argument('--manifest-path', help='Path to AndroidManifest.xml') parser.add_argument('--classpath', default=[], action='append', help='GYP-list of classpath .jar files') parser.add_argument('--processed-config-path', help='Path to processed lint suppressions file.') parser.add_argument('--resource-dir', help='Path to resource dir.') parser.add_argument('--resource-sources', default=[], action='append', help='GYP-list of resource sources (directories with ' 'resources or archives created by resource-generating ' 'tasks.') parser.add_argument('--silent', action='store_true', help='If set, script will not log anything.') parser.add_argument('--src-dirs', help='Directories containing java files.') parser.add_argument('--srcjars', help='GN list of included srcjars.') parser.add_argument( '--min-sdk-version', required=True, help='Minimal SDK version to lint against.') parser.add_argument( '--manifest-package', help='Package name of the AndroidManifest.xml.') args = parser.parse_args(build_utils.ExpandFileArgs(sys.argv[1:])) sources = [] if args.src_dirs: src_dirs = build_utils.ParseGnList(args.src_dirs) sources = _FindInDirectories(src_dirs, '*.java') elif args.java_sources_file: sources.extend(build_utils.ReadSourcesList(args.java_sources_file)) if args.config_path and not args.processed_config_path: parser.error('--config-path specified without --processed-config-path') elif args.processed_config_path and not args.config_path: parser.error('--processed-config-path specified without --config-path') input_paths = [ args.lint_path, args.platform_xml_path, ] if args.config_path: input_paths.append(args.config_path) if args.jar_path: input_paths.append(args.jar_path) if args.manifest_path: input_paths.append(args.manifest_path) if sources: input_paths.extend(sources) classpath = [] for gyp_list in args.classpath: classpath.extend(build_utils.ParseGnList(gyp_list)) input_paths.extend(classpath) resource_sources = [] if args.resource_dir: # Backward compatibility with GYP resource_sources += [ args.resource_dir ] for gyp_list in args.resource_sources: resource_sources += build_utils.ParseGnList(gyp_list) for resource_source in resource_sources: if os.path.isdir(resource_source): input_paths.extend(build_utils.FindInDirectory(resource_source, '*')) else: input_paths.append(resource_source) input_strings = [ args.can_fail_build, args.include_unexpected_failures, args.silent, ] if args.android_sdk_version: input_strings.append(args.android_sdk_version) if args.processed_config_path: input_strings.append(args.processed_config_path) disable = [] if args.disable: disable = build_utils.ParseGnList(args.disable) input_strings.extend(disable) output_paths = [args.result_path, args.processed_config_path] build_utils.CallAndWriteDepfileIfStale( lambda: _OnStaleMd5(args.lint_path, args.config_path, args.processed_config_path, args.manifest_path, args.result_path, args.product_dir, sources, args.jar_path, args.cache_dir, args.android_sdk_version, args.srcjars, args.min_sdk_version, args.manifest_package, resource_sources, disable=disable, classpath=classpath, can_fail_build=args.can_fail_build, include_unexpected=args.include_unexpected_failures, silent=args.silent), args, input_paths=input_paths, input_strings=input_strings, output_paths=output_paths, depfile_deps=classpath, add_pydeps=False)
def _ParseOptions(args): parser = optparse.OptionParser() build_utils.AddDepfileOption(parser) parser.add_option('--proguard-path', help='Path to the proguard.jar to use.') parser.add_option('--r8-path', help='Path to the R8.jar to use.') parser.add_option('--input-paths', help='Paths to the .jar files proguard should run on.') parser.add_option('--output-path', help='Path to the generated .jar file.') parser.add_option('--proguard-configs', action='append', help='Paths to proguard configuration files.') parser.add_option('--proguard-config-exclusions', default='', help='GN list of paths to proguard configuration files ' 'included by --proguard-configs, but that should ' 'not actually be included.') parser.add_option('--apply-mapping', help='Path to proguard mapping to apply.') parser.add_option('--mapping-output', help='Path for proguard to output mapping file to.') parser.add_option('--classpath', action='append', help='Classpath for proguard.') parser.add_option('--main-dex-rules-path', action='append', help='Paths to main dex rules for multidex' '- only works with R8.') parser.add_option('--min-api', default='', help='Minimum Android API level compatibility.') parser.add_option('--verbose', '-v', action='store_true', help='Print all proguard output') options, _ = parser.parse_args(args) assert not options.main_dex_rules_path or options.r8_path, \ "R8 must be enabled to pass main dex rules." assert not options.min_api or options.r8_path, \ "R8 must be enabled to pass min api." classpath = [] for arg in options.classpath: classpath += build_utils.ParseGnList(arg) options.classpath = classpath configs = [] for arg in options.proguard_configs: configs += build_utils.ParseGnList(arg) options.proguard_configs = configs options.proguard_config_exclusions = (build_utils.ParseGnList( options.proguard_config_exclusions)) options.input_paths = build_utils.ParseGnList(options.input_paths) if not options.mapping_output: options.mapping_output = options.output_path + ".mapping" if options.apply_mapping: options.apply_mapping = os.path.abspath(options.apply_mapping) return options
def _ParseOptions(args): parser = optparse.OptionParser() build_utils.AddDepfileOption(parser) parser.add_option('--proguard-path', help='Path to the proguard.jar to use.') parser.add_option('--r8-path', help='Path to the R8.jar to use.') parser.add_option('--input-paths', help='Paths to the .jar files proguard should run on.') parser.add_option('--output-path', help='Path to the generated .jar file.') parser.add_option('--proguard-configs', action='append', help='Paths to proguard configuration files.') parser.add_option('--proguard-config-exclusions', default='', help='GN list of paths to proguard configuration files ' 'included by --proguard-configs, but that should ' 'not actually be included.') parser.add_option('--apply-mapping', help='Path to proguard mapping to apply.') parser.add_option('--mapping-output', help='Path for proguard to output mapping file to.') parser.add_option('--extra-mapping-output-paths', help='Additional paths to copy output mapping file to.') parser.add_option('--output-config', help='Path to write the merged proguard config file to.') parser.add_option( '--expected-configs-file', help='Path to a file containing the expected merged proguard configs') parser.add_option( '--verify-expected-configs', action='store_true', help='Fail if the expected merged proguard configs differ from the ' 'generated merged proguard configs.') parser.add_option('--classpath', action='append', help='Classpath for proguard.') parser.add_option('--main-dex-rules-path', action='append', help='Paths to main dex rules for multidex' '- only works with R8.') parser.add_option('--min-api', default='', help='Minimum Android API level compatibility.') parser.add_option('--verbose', '-v', action='store_true', help='Print all proguard output') parser.add_option( '--repackage-classes', help='Unique package name given to an asynchronously proguarded module' ) options, _ = parser.parse_args(args) assert not options.main_dex_rules_path or options.r8_path, \ 'R8 must be enabled to pass main dex rules.' classpath = [] for arg in options.classpath: classpath += build_utils.ParseGnList(arg) options.classpath = classpath configs = [] for arg in options.proguard_configs: configs += build_utils.ParseGnList(arg) options.proguard_configs = configs options.proguard_config_exclusions = (build_utils.ParseGnList( options.proguard_config_exclusions)) options.input_paths = build_utils.ParseGnList(options.input_paths) if not options.mapping_output: options.mapping_output = options.output_path + '.mapping' if options.apply_mapping: options.apply_mapping = os.path.abspath(options.apply_mapping) return options
def _OnStaleMd5(lint_path, config_path, processed_config_path, manifest_path, result_path, product_dir, sources, jar_path, cache_dir, android_sdk_version, srcjars, min_sdk_version, manifest_package, resource_sources, disable=None, classpath=None, can_fail_build=False, include_unexpected=False, silent=False): def _RebasePath(path): """Returns relative path to top-level src dir. Args: path: A path relative to cwd. """ ret = os.path.relpath(os.path.abspath(path), build_utils.DIR_SOURCE_ROOT) # If it's outside of src/, just use abspath. if ret.startswith('..'): ret = os.path.abspath(path) return ret def _ProcessConfigFile(): if not config_path or not processed_config_path: return if not build_utils.IsTimeStale(processed_config_path, [config_path]): return with open(config_path, 'rb') as f: content = f.read().replace( 'PRODUCT_DIR', _RebasePath(product_dir)) with open(processed_config_path, 'wb') as f: f.write(content) def _ProcessResultFile(): with open(result_path, 'rb') as f: content = f.read().replace( _RebasePath(product_dir), 'PRODUCT_DIR') with open(result_path, 'wb') as f: f.write(content) def _ParseAndShowResultFile(): dom = minidom.parse(result_path) issues = dom.getElementsByTagName('issue') if not silent: print(file=sys.stderr) for issue in issues: issue_id = issue.attributes['id'].value message = issue.attributes['message'].value location_elem = issue.getElementsByTagName('location')[0] path = location_elem.attributes['file'].value line = location_elem.getAttribute('line') if line: error = '%s:%s %s: %s [warning]' % (path, line, message, issue_id) else: # Issues in class files don't have a line number. error = '%s %s: %s [warning]' % (path, message, issue_id) print(error.encode('utf-8'), file=sys.stderr) for attr in ['errorLine1', 'errorLine2']: error_line = issue.getAttribute(attr) if error_line: print(error_line.encode('utf-8'), file=sys.stderr) return len(issues) with build_utils.TempDir() as temp_dir: _ProcessConfigFile() cmd = [ _RebasePath(lint_path), '-Werror', '--exitcode', '--showall', '--xml', _RebasePath(result_path), ] if jar_path: # --classpath is just for .class files for this one target. cmd.extend(['--classpath', _RebasePath(jar_path)]) if processed_config_path: cmd.extend(['--config', _RebasePath(processed_config_path)]) tmp_dir_counter = [0] def _NewTempSubdir(prefix, append_digit=True): # Helper function to create a new sub directory based on the number of # subdirs created earlier. if append_digit: tmp_dir_counter[0] += 1 prefix += str(tmp_dir_counter[0]) new_dir = os.path.join(temp_dir, prefix) os.makedirs(new_dir) return new_dir resource_dirs = [] for resource_source in resource_sources: if os.path.isdir(resource_source): resource_dirs.append(resource_source) else: # This is a zip file with generated resources (e. g. strings from GRD). # Extract it to temporary folder. resource_dir = _NewTempSubdir(resource_source, append_digit=False) resource_dirs.append(resource_dir) build_utils.ExtractAll(resource_source, path=resource_dir) for resource_dir in resource_dirs: cmd.extend(['--resources', _RebasePath(resource_dir)]) if classpath: # --libraries is the classpath (excluding active target). cp = ':'.join(_RebasePath(p) for p in classpath) cmd.extend(['--libraries', cp]) # There may be multiple source files with the same basename (but in # different directories). It is difficult to determine what part of the path # corresponds to the java package, and so instead just link the source files # into temporary directories (creating a new one whenever there is a name # conflict). def PathInDir(d, src): subpath = os.path.join(d, _RebasePath(src)) subdir = os.path.dirname(subpath) if not os.path.exists(subdir): os.makedirs(subdir) return subpath src_dirs = [] for src in sources: src_dir = None for d in src_dirs: if not os.path.exists(PathInDir(d, src)): src_dir = d break if not src_dir: src_dir = _NewTempSubdir('SRC_ROOT') src_dirs.append(src_dir) cmd.extend(['--sources', _RebasePath(src_dir)]) os.symlink(os.path.abspath(src), PathInDir(src_dir, src)) if srcjars: srcjar_paths = build_utils.ParseGnList(srcjars) if srcjar_paths: srcjar_dir = _NewTempSubdir('SRC_ROOT') cmd.extend(['--sources', _RebasePath(srcjar_dir)]) for srcjar in srcjar_paths: build_utils.ExtractAll(srcjar, path=srcjar_dir) if disable: cmd.extend(['--disable', ','.join(disable)]) project_dir = _NewTempSubdir('SRC_ROOT') if android_sdk_version: # Create dummy project.properies file in a temporary "project" directory. # It is the only way to add Android SDK to the Lint's classpath. Proper # classpath is necessary for most source-level checks. with open(os.path.join(project_dir, 'project.properties'), 'w') \ as propfile: print('target=android-{}'.format(android_sdk_version), file=propfile) # Put the manifest in a temporary directory in order to avoid lint detecting # sibling res/ and src/ directories (which should be pass explicitly if they # are to be included). if not manifest_path: manifest_path = os.path.join( build_utils.DIR_SOURCE_ROOT, 'build', 'android', 'AndroidManifest.xml') lint_manifest_path = os.path.join(project_dir, 'AndroidManifest.xml') shutil.copyfile(os.path.abspath(manifest_path), lint_manifest_path) # Check that minSdkVersion and package is correct and add it to the manifest # in case it does not exist. doc, manifest, _ = manifest_utils.ParseManifest(lint_manifest_path) manifest_utils.AssertUsesSdk(manifest, min_sdk_version) manifest_utils.AssertPackage(manifest, manifest_package) uses_sdk = manifest.find('./uses-sdk') if uses_sdk is None: uses_sdk = ElementTree.Element('uses-sdk') manifest.insert(0, uses_sdk) uses_sdk.set('{%s}minSdkVersion' % manifest_utils.ANDROID_NAMESPACE, min_sdk_version) if manifest_package: manifest.set('package', manifest_package) manifest_utils.SaveManifest(doc, lint_manifest_path) cmd.append(project_dir) if os.path.exists(result_path): os.remove(result_path) env = os.environ.copy() stderr_filter = None if cache_dir: env['_JAVA_OPTIONS'] = '-Duser.home=%s' % _RebasePath(cache_dir) # When _JAVA_OPTIONS is set, java prints to stderr: # Picked up _JAVA_OPTIONS: ... # # We drop all lines that contain _JAVA_OPTIONS from the output stderr_filter = lambda l: re.sub(r'.*_JAVA_OPTIONS.*\n?', '', l) def fail_func(returncode, stderr): if returncode != 0: return True if (include_unexpected and 'Unexpected failure during lint analysis' in stderr): return True return False try: build_utils.CheckOutput(cmd, cwd=build_utils.DIR_SOURCE_ROOT, env=env or None, stderr_filter=stderr_filter, fail_func=fail_func) except build_utils.CalledProcessError: # There is a problem with lint usage if not os.path.exists(result_path): raise # Sometimes produces empty (almost) files: if os.path.getsize(result_path) < 10: if can_fail_build: raise elif not silent: traceback.print_exc() return # There are actual lint issues try: num_issues = _ParseAndShowResultFile() except Exception: # pylint: disable=broad-except if not silent: print('Lint created unparseable xml file...') print('File contents:') with open(result_path) as f: print(f.read()) if can_fail_build: traceback.print_exc() if can_fail_build: raise else: return _ProcessResultFile() if num_issues == 0 and include_unexpected: msg = 'Please refer to output above for unexpected lint failures.\n' else: msg = ('\nLint found %d new issues.\n' ' - For full explanation, please refer to %s\n' ' - For more information about lint and how to fix lint issues,' ' please refer to %s\n' % (num_issues, _RebasePath(result_path), _LINT_MD_URL)) if not silent: print(msg, file=sys.stderr) if can_fail_build: raise Exception('Lint failed.')
def main(args): args = build_utils.ExpandFileArgs(args) options = _ParseOptions(args) libraries = [] for p in options.classpath: # If a jar is part of input no need to include it as library jar. if p not in libraries and p not in options.input_paths: libraries.append(p) # TODO(agrieve): Remove proguard usages. if options.r8_path: temp_config_string = '' with build_utils.TempDir() as tmp_dir: tmp_mapping_path = os.path.join(tmp_dir, 'mapping.txt') tmp_proguard_config_path = os.path.join(tmp_dir, 'proguard_config.txt') # If there is no output (no classes are kept), this prevents this script # from failing. build_utils.Touch(tmp_mapping_path) f = cStringIO.StringIO() proguard_util.WriteFlagsFile(options.proguard_configs, f, exclude_generated=True) merged_configs = f.getvalue() # Fix up line endings (third_party configs can have windows endings) merged_configs = merged_configs.replace('\r', '') f.close() print_stdout = '-whyareyoukeeping' in merged_configs if options.output_path.endswith('.dex'): with build_utils.TempDir() as tmp_dex_dir: cmd, temp_config_string = _CreateR8Command( options, tmp_mapping_path, tmp_dex_dir, tmp_proguard_config_path, libraries) build_utils.CheckOutput(cmd, print_stdout=print_stdout) _MoveTempDexFile(tmp_dex_dir, options.output_path) else: cmd, temp_config_string = _CreateR8Command( options, tmp_mapping_path, options.output_path, tmp_proguard_config_path, libraries) build_utils.CheckOutput(cmd, print_stdout=print_stdout) # Copy output files to correct locations. with build_utils.AtomicOutput(options.mapping_output) as mapping: # Mapping files generated by R8 include comments that may break # some of our tooling so remove those. with open(tmp_mapping_path) as tmp: mapping.writelines(l for l in tmp if not l.startswith('#')) for output in build_utils.ParseGnList( options.extra_mapping_output_paths): shutil.copy(tmp_mapping_path, output) with build_utils.AtomicOutput(options.output_config) as f: f.write(merged_configs) if temp_config_string: f.write(_GENERATED_PROGUARD_HEADER) f.write(temp_config_string) if options.expected_configs_file: _VerifyExpectedConfigs(options.expected_configs_file, options.output_config, options.verify_expected_configs) other_inputs = [] if options.apply_mapping: other_inputs += options.apply_mapping build_utils.WriteDepfile(options.depfile, options.output_path, inputs=options.proguard_configs + options.input_paths + libraries + other_inputs, add_pydeps=False) else: proguard = proguard_util.ProguardCmdBuilder(options.proguard_path) proguard.injars(options.input_paths) proguard.configs(options.proguard_configs) proguard.config_exclusions(options.proguard_config_exclusions) proguard.outjar(options.output_path) proguard.mapping_output(options.mapping_output) proguard.libraryjars(libraries) proguard.verbose(options.verbose) proguard.min_api(options.min_api) # Do not consider the temp file as an input since its name is random. input_paths = proguard.GetInputs() with tempfile.NamedTemporaryFile() as f: if options.apply_mapping: input_paths.append(options.apply_mapping) # Maintain only class name mappings in the .mapping file in order to # work around what appears to be a ProGuard bug in -applymapping: # method 'int close()' is not being kept as 'a', but remapped to 'c' _RemoveMethodMappings(options.apply_mapping, f) proguard.mapping(f.name) input_strings = proguard.build() if f.name in input_strings: input_strings[input_strings.index(f.name)] = '$M' build_utils.CallAndWriteDepfileIfStale( proguard.CheckOutput, options, input_paths=input_paths, input_strings=input_strings, output_paths=proguard.GetOutputs(), depfile_deps=proguard.GetDepfileDeps(), add_pydeps=False)
def main(args): parser = argparse.ArgumentParser() parser.add_argument('--script-output-path', help='Output path for executable script.') parser.add_argument('--depfile', help='Path to the depfile. This must be specified as ' "the action's first output.") parser.add_argument('--test-runner-path', help='Path to test_runner.py (optional).') # We need to intercept any test runner path arguments and make all # of the paths relative to the output script directory. group = parser.add_argument_group('Test runner path arguments.') group.add_argument('--additional-apk', action='append', dest='additional_apks', default=[]) group.add_argument('--additional-apk-list') group.add_argument('--apk-under-test') group.add_argument('--apk-under-test-incremental-install-script') group.add_argument('--executable-dist-dir') group.add_argument('--isolate-file-path') group.add_argument('--output-directory') group.add_argument('--runtime-deps-path') group.add_argument('--test-apk') group.add_argument('--test-apk-incremental-install-script') group.add_argument('--coverage-dir') args, test_runner_args = parser.parse_known_args( build_utils.ExpandFileArgs(args)) def RelativizePathToScript(path): """Returns the path relative to the output script directory.""" return os.path.relpath(path, os.path.dirname(args.script_output_path)) test_runner_path = args.test_runner_path or os.path.join( os.path.dirname(__file__), os.path.pardir, 'test_runner.py') test_runner_path = RelativizePathToScript(test_runner_path) test_runner_path_args = [] if args.additional_apk_list: args.additional_apks.extend( build_utils.ParseGnList(args.additional_apk_list)) if args.additional_apks: test_runner_path_args.extend( ('--additional-apk', RelativizePathToScript(a)) for a in args.additional_apks) if args.apk_under_test: test_runner_path_args.append( ('--apk-under-test', RelativizePathToScript(args.apk_under_test))) if args.apk_under_test_incremental_install_script: test_runner_path_args.append( ('--apk-under-test-incremental-install-script', RelativizePathToScript( args.apk_under_test_incremental_install_script))) if args.executable_dist_dir: test_runner_path_args.append( ('--executable-dist-dir', RelativizePathToScript(args.executable_dist_dir))) if args.isolate_file_path: test_runner_path_args.append( ('--isolate-file-path', RelativizePathToScript(args.isolate_file_path))) if args.output_directory: test_runner_path_args.append( ('--output-directory', RelativizePathToScript(args.output_directory))) if args.runtime_deps_path: test_runner_path_args.append( ('--runtime-deps-path', RelativizePathToScript(args.runtime_deps_path))) if args.test_apk: test_runner_path_args.append( ('--test-apk', RelativizePathToScript(args.test_apk))) if args.test_apk_incremental_install_script: test_runner_path_args.append( ('--test-apk-incremental-install-script', RelativizePathToScript(args.test_apk_incremental_install_script))) if args.coverage_dir: test_runner_path_args.append( ('--coverage-dir', RelativizePathToScript(args.coverage_dir))) with open(args.script_output_path, 'w') as script: script.write( SCRIPT_TEMPLATE.format( test_runner_path=str(test_runner_path), test_runner_args=str(test_runner_args), test_runner_path_args=str(test_runner_path_args))) os.chmod(args.script_output_path, 0750) if args.depfile: build_utils.WriteDepfile(args.depfile, args.script_output_path)
def _ParseArgs(args): args = build_utils.ExpandFileArgs(args) parser = optparse.OptionParser() build_utils.AddDepfileOption(parser) parser.add_option('--android-sdk-tools', help='Android sdk build tools directory.') parser.add_option('--output-directory', default=os.getcwd(), help='Path to the output build directory.') parser.add_option('--dex-path', help='Dex output path.') parser.add_option('--configuration-name', help='The build CONFIGURATION_NAME.') parser.add_option('--proguard-enabled', help='"true" if proguard is enabled.') parser.add_option('--debug-build-proguard-enabled', help='"true" if proguard is enabled for debug build.') parser.add_option('--proguard-enabled-input-path', help=('Path to dex in Release mode when proguard ' 'is enabled.')) parser.add_option('--no-locals', default='0', help='Exclude locals list from the dex file.') parser.add_option('--incremental', action='store_true', help='Enable incremental builds when possible.') parser.add_option('--inputs', help='A list of additional input paths.') parser.add_option('--excluded-paths', help='A list of paths to exclude from the dex file.') parser.add_option('--main-dex-list-path', help='A file containing a list of the classes to ' 'include in the main dex.') parser.add_option( '--multidex-configuration-path', help='A JSON file containing multidex build configuration.') parser.add_option('--multi-dex', default=False, action='store_true', help='Generate multiple dex files.') options, paths = parser.parse_args(args) required_options = ('android_sdk_tools', ) build_utils.CheckOptions(options, parser, required=required_options) if options.multidex_configuration_path: with open(options.multidex_configuration_path) as multidex_config_file: multidex_config = json.loads(multidex_config_file.read()) options.multi_dex = multidex_config.get('enabled', False) if options.multi_dex and not options.main_dex_list_path: logging.warning( 'multidex cannot be enabled without --main-dex-list-path') options.multi_dex = False elif options.main_dex_list_path and not options.multi_dex: logging.warning( '--main-dex-list-path is unused if multidex is not enabled') if options.inputs: options.inputs = build_utils.ParseGnList(options.inputs) _CheckFilePathsEndWithJar(parser, options.inputs) if options.excluded_paths: options.excluded_paths = build_utils.ParseGnList( options.excluded_paths) if options.proguard_enabled_input_path: _CheckFilePathEndsWithJar(parser, options.proguard_enabled_input_path) _CheckFilePathsEndWithJar(parser, paths) return options, paths
def _ParseArgs(args): """Parses command line options. Returns: An options object as from optparse.OptionsParser.parse_args() """ parser = optparse.OptionParser() build_utils.AddDepfileOption(parser) parser.add_option('--android-sdk-jar', help='the path to android jar file.') parser.add_option('--aapt-path', help='path to the Android aapt tool') parser.add_option('--non-constant-id', action='store_true') parser.add_option('--android-manifest', help='AndroidManifest.xml path') parser.add_option('--custom-package', help='Java package for R.java') parser.add_option( '--shared-resources', action='store_true', help='Make a resource package that can be loaded by a different' 'application at runtime to access the package\'s resources.') parser.add_option( '--app-as-shared-lib', action='store_true', help='Make a resource package that can be loaded as shared library.') parser.add_option( '--shared-resources-whitelist', help='An R.txt file acting as a whitelist for resources that should be ' 'non-final and have their package ID changed at runtime in R.java. If no ' 'whitelist is provided, then everything is whitelisted.') parser.add_option('--resource-dirs', default='[]', help='Directories containing resources of this target.') parser.add_option('--dependencies-res-zips', help='Resources from dependents.') parser.add_option('--resource-zip-out', help='Path for output zipped resources.') parser.add_option('--srcjar-out', help='Path to srcjar to contain generated R.java.') parser.add_option('--r-text-out', help='Path to store the generated R.txt file.') parser.add_option('--r-text-in', help='Path to pre-existing R.txt for these resources. ' 'Resource names from it will be used to generate R.java ' 'instead of aapt-generated R.txt.') parser.add_option('--proguard-file', help='Path to proguard.txt generated file') parser.add_option('--proguard-file-main-dex', help='Path to proguard.txt generated file for main dex') parser.add_option( '--v14-skip', action="store_true", help='Do not generate nor verify v14 resources') parser.add_option( '--extra-res-packages', help='Additional package names to generate R.java files for') parser.add_option( '--extra-r-text-files', help='For each additional package, the R.txt file should contain a ' 'list of resources to be included in the R.java file in the format ' 'generated by aapt') parser.add_option('--support-zh-hk', action='store_true', help='Use zh-rTW resources for zh-rHK.') parser.add_option('--stamp', help='File to touch on success') parser.add_option('--debuggable', action='store_true', help='Whether to add android:debuggable="true"') parser.add_option('--version-code', help='Version code for apk.') parser.add_option('--version-name', help='Version name for apk.') parser.add_option('--no-compress', help='disables compression for the ' 'given comma separated list of extensions') parser.add_option( '--create-density-splits', action='store_true', help='Enables density splits') parser.add_option('--language-splits', default='[]', help='GN list of languages to create splits for') parser.add_option('--locale-whitelist', default='[]', help='GN list of languages to include. All other language ' 'configs will be stripped out. List may include ' 'a combination of Android locales or Chrome locales.') parser.add_option('--apk-path', help='Path to output (partial) apk.') parser.add_option('--exclude-xxxhdpi', action='store_true', help='Do not include xxxhdpi drawables.') parser.add_option('--xxxhdpi-whitelist', default='[]', help='GN list of globs that say which xxxhdpi images to ' 'include even when --exclude-xxxhdpi is set.') parser.add_option('--png-to-webp', action='store_true', help='Convert png files to webp format.') parser.add_option('--webp-binary', default='', help='Path to the cwebp binary.') parser.add_option('--no-xml-namespaces', action='store_true', help='Whether to strip xml namespaces from processed xml ' 'resources') options, positional_args = parser.parse_args(args) if positional_args: parser.error('No positional arguments should be given.') # Check that required options have been provided. required_options = ( 'android_sdk_jar', 'aapt_path', 'dependencies_res_zips', ) build_utils.CheckOptions(options, parser, required=required_options) options.resource_dirs = build_utils.ParseGnList(options.resource_dirs) options.dependencies_res_zips = ( build_utils.ParseGnList(options.dependencies_res_zips)) options.language_splits = build_utils.ParseGnList(options.language_splits) options.locale_whitelist = build_utils.ParseGnList(options.locale_whitelist) options.xxxhdpi_whitelist = build_utils.ParseGnList(options.xxxhdpi_whitelist) # Don't use [] as default value since some script explicitly pass "". if options.extra_res_packages: options.extra_res_packages = ( build_utils.ParseGnList(options.extra_res_packages)) else: options.extra_res_packages = [] if options.extra_r_text_files: options.extra_r_text_files = ( build_utils.ParseGnList(options.extra_r_text_files)) else: options.extra_r_text_files = [] return options
def main(argv): arg_parser = argparse.ArgumentParser() build_utils.AddDepfileOption(arg_parser) arg_parser.add_argument('--sources-files', required=True, help='A list of .sources files which contain Java ' 'file paths.') arg_parser.add_argument('--header-path', help='Path to output header file (optional).') arg_parser.add_argument( '--srcjar-path', required=True, help='Path to output srcjar for GEN_JNI.java (Or J/N.java if proxy' ' hash is enabled).') arg_parser.add_argument( '--sources-blacklist', default=[], help='A list of Java files which should be ignored ' 'by the parser.') arg_parser.add_argument( '--namespace', default='', help='Namespace to wrap the registration functions ' 'into.') # TODO(crbug.com/898261) hook these flags up to the build config to enable # mocking in instrumentation tests arg_parser.add_argument( '--enable_proxy_mocks', default=False, action='store_true', help='Allows proxy native impls to be mocked through Java.') arg_parser.add_argument( '--require_mocks', default=False, action='store_true', help='Requires all used native implementations to have a mock set when ' 'called. Otherwise an exception will be thrown.') arg_parser.add_argument( '--use_proxy_hash', action='store_true', help='Enables hashing of the native declaration for methods in ' 'an @JniNatives interface') args = arg_parser.parse_args(build_utils.ExpandFileArgs(argv[1:])) if not args.enable_proxy_mocks and args.require_mocks: arg_parser.error( 'Invalid arguments: --require_mocks without --enable_proxy_mocks. ' 'Cannot require mocks if they are not enabled.') args.sources_files = build_utils.ParseGnList(args.sources_files) proxy_opts = ProxyOptions(use_hash=args.use_proxy_hash, require_mocks=args.require_mocks, enable_mocks=args.enable_proxy_mocks) java_file_paths = [] for f in args.sources_files: # Skip generated files, since the GN targets do not declare any deps. java_file_paths.extend( p for p in build_utils.ReadSourcesList(f) if p.startswith('..') and p not in args.sources_blacklist) _Generate(java_file_paths, args.srcjar_path, proxy_opts=proxy_opts, header_path=args.header_path, namespace=args.namespace) if args.depfile: build_utils.WriteDepfile(args.depfile, args.srcjar_path, args.sources_files + java_file_paths, add_pydeps=False)
def main(argv): parser = optparse.OptionParser() build_utils.AddDepfileOption(parser) parser.add_option('--build-config', help='Path to build_config output.') parser.add_option( '--type', help='Type of this target (e.g. android_library).') parser.add_option( '--deps-configs', help='List of paths for dependency\'s build_config files. ') # android_resources options parser.add_option('--srcjar', help='Path to target\'s resources srcjar.') parser.add_option('--resources-zip', help='Path to target\'s resources zip.') parser.add_option('--r-text', help='Path to target\'s R.txt file.') parser.add_option('--package-name', help='Java package name for these resources.') parser.add_option('--android-manifest', help='Path to android manifest.') parser.add_option('--is-locale-resource', action='store_true', help='Whether it is locale resource.') parser.add_option('--resource-dirs', action='append', default=[], help='GYP-list of resource dirs') # android_assets options parser.add_option('--asset-sources', help='List of asset sources.') parser.add_option('--asset-renaming-sources', help='List of asset sources with custom destinations.') parser.add_option('--asset-renaming-destinations', help='List of asset custom destinations.') parser.add_option('--disable-asset-compression', action='store_true', help='Whether to disable asset compression.') # java library options parser.add_option('--jar-path', help='Path to target\'s jar output.') parser.add_option('--java-sources-file', help='Path to .sources file') parser.add_option('--bundled-srcjars', help='GYP-list of .srcjars that have been included in this java_library.') parser.add_option('--supports-android', action='store_true', help='Whether this library supports running on the Android platform.') parser.add_option('--requires-android', action='store_true', help='Whether this library requires running on the Android platform.') parser.add_option('--bypass-platform-checks', action='store_true', help='Bypass checks for support/require Android platform.') parser.add_option('--extra-classpath-jars', help='GYP-list of .jar files to include on the classpath when compiling, ' 'but not to include in the final binary.') # android library options parser.add_option('--dex-path', help='Path to target\'s dex output.') # native library options parser.add_option('--shared-libraries-runtime-deps', help='Path to file containing runtime deps for shared ' 'libraries.') # apk options parser.add_option('--apk-path', help='Path to the target\'s apk output.') parser.add_option('--incremental-apk-path', help="Path to the target's incremental apk output.") parser.add_option('--incremental-install-script-path', help="Path to the target's generated incremental install " "script.") parser.add_option('--tested-apk-config', help='Path to the build config of the tested apk (for an instrumentation ' 'test apk).') parser.add_option('--proguard-enabled', action='store_true', help='Whether proguard is enabled for this apk.') parser.add_option('--proguard-info', help='Path to the proguard .info output for this apk.') parser.add_option('--has-alternative-locale-resource', action='store_true', help='Whether there is alternative-locale-resource in direct deps') parser.add_option('--fail', help='GYP-list of error message lines to fail with.') options, args = parser.parse_args(argv) if args: parser.error('No positional arguments should be given.') if options.fail: parser.error('\n'.join(build_utils.ParseGnList(options.fail))) required_options_map = { 'java_binary': ['build_config', 'jar_path'], 'java_library': ['build_config', 'jar_path'], 'java_prebuilt': ['build_config', 'jar_path'], 'android_assets': ['build_config'], 'android_resources': ['build_config', 'resources_zip'], 'android_apk': ['build_config', 'jar_path', 'dex_path', 'resources_zip'], 'deps_dex': ['build_config', 'dex_path'], 'resource_rewriter': ['build_config'], 'group': ['build_config'], } required_options = required_options_map.get(options.type) if not required_options: raise Exception('Unknown type: <%s>' % options.type) build_utils.CheckOptions(options, parser, required_options) # Java prebuilts are the same as libraries except for in gradle files. is_java_prebuilt = options.type == 'java_prebuilt' if is_java_prebuilt: options.type = 'java_library' if options.type == 'java_library': if options.supports_android and not options.dex_path: raise Exception('java_library that supports Android requires a dex path.') if options.requires_android and not options.supports_android: raise Exception( '--supports-android is required when using --requires-android') direct_deps_config_paths = build_utils.ParseGnList(options.deps_configs) direct_deps_config_paths = _FilterDepsPaths(direct_deps_config_paths, options.type) deps = Deps(direct_deps_config_paths) all_inputs = deps.AllConfigPaths() + build_utils.GetPythonDependencies() # Remove other locale resources if there is alternative_locale_resource in # direct deps. if options.has_alternative_locale_resource: alternative = [r['path'] for r in deps.Direct('android_resources') if r.get('is_locale_resource')] # We can only have one locale resources in direct deps. if len(alternative) != 1: raise Exception('The number of locale resource in direct deps is wrong %d' % len(alternative)) unwanted = [r['path'] for r in deps.All('android_resources') if r.get('is_locale_resource') and r['path'] not in alternative] for p in unwanted: deps.RemoveNonDirectDep(p) direct_library_deps = deps.Direct('java_library') all_library_deps = deps.All('java_library') all_resources_deps = deps.All('android_resources') # Resources should be ordered with the highest-level dependency first so that # overrides are done correctly. all_resources_deps.reverse() if options.type == 'android_apk' and options.tested_apk_config: tested_apk_deps = Deps([options.tested_apk_config]) tested_apk_resources_deps = tested_apk_deps.All('android_resources') all_resources_deps = [ d for d in all_resources_deps if not d in tested_apk_resources_deps] # Initialize some common config. # Any value that needs to be queryable by dependents must go within deps_info. config = { 'deps_info': { 'name': os.path.basename(options.build_config), 'path': options.build_config, 'type': options.type, 'deps_configs': direct_deps_config_paths }, # Info needed only by generate_gradle.py. 'gradle': {} } deps_info = config['deps_info'] gradle = config['gradle'] # Required for generating gradle files. if options.type == 'java_library': deps_info['is_prebuilt'] = is_java_prebuilt if options.android_manifest: gradle['android_manifest'] = options.android_manifest if options.type in ('java_binary', 'java_library', 'android_apk'): if options.java_sources_file: gradle['java_sources_file'] = options.java_sources_file if options.bundled_srcjars: gradle['bundled_srcjars'] = ( build_utils.ParseGnList(options.bundled_srcjars)) gradle['dependent_prebuilt_jars'] = deps.PrebuiltJarPaths() gradle['dependent_android_projects'] = [] gradle['dependent_java_projects'] = [] for c in direct_library_deps: if not c['is_prebuilt']: if c['requires_android']: gradle['dependent_android_projects'].append(c['path']) else: gradle['dependent_java_projects'].append(c['path']) if (options.type in ('java_binary', 'java_library') and not options.bypass_platform_checks): deps_info['requires_android'] = options.requires_android deps_info['supports_android'] = options.supports_android deps_require_android = (all_resources_deps + [d['name'] for d in all_library_deps if d['requires_android']]) deps_not_support_android = ( [d['name'] for d in all_library_deps if not d['supports_android']]) if deps_require_android and not options.requires_android: raise Exception('Some deps require building for the Android platform: ' + str(deps_require_android)) if deps_not_support_android and options.supports_android: raise Exception('Not all deps support the Android platform: ' + str(deps_not_support_android)) if options.type in ('java_binary', 'java_library', 'android_apk'): deps_info['jar_path'] = options.jar_path if options.type == 'android_apk' or options.supports_android: deps_info['dex_path'] = options.dex_path if options.type == 'android_apk': deps_info['apk_path'] = options.apk_path deps_info['incremental_apk_path'] = options.incremental_apk_path deps_info['incremental_install_script_path'] = ( options.incremental_install_script_path) # Classpath values filled in below (after applying tested_apk_config). config['javac'] = {} if options.type in ('java_binary', 'java_library'): # Only resources might have srcjars (normal srcjar targets are listed in # srcjar_deps). A resource's srcjar contains the R.java file for those # resources, and (like Android's default build system) we allow a library to # refer to the resources in any of its dependents. config['javac']['srcjars'] = [ c['srcjar'] for c in all_resources_deps if 'srcjar' in c] # Used to strip out R.class for android_prebuilt()s. if options.type == 'java_library': config['javac']['resource_packages'] = [ c['package_name'] for c in all_resources_deps if 'package_name' in c] if options.type == 'android_apk': # Apks will get their resources srcjar explicitly passed to the java step. config['javac']['srcjars'] = [] if options.type == 'android_assets': all_asset_sources = [] if options.asset_renaming_sources: all_asset_sources.extend( build_utils.ParseGnList(options.asset_renaming_sources)) if options.asset_sources: all_asset_sources.extend(build_utils.ParseGnList(options.asset_sources)) deps_info['assets'] = { 'sources': all_asset_sources } if options.asset_renaming_destinations: deps_info['assets']['outputs'] = ( build_utils.ParseGnList(options.asset_renaming_destinations)) if options.disable_asset_compression: deps_info['assets']['disable_compression'] = True if options.type == 'android_resources': deps_info['resources_zip'] = options.resources_zip if options.srcjar: deps_info['srcjar'] = options.srcjar if options.android_manifest: manifest = AndroidManifest(options.android_manifest) deps_info['package_name'] = manifest.GetPackageName() if options.package_name: deps_info['package_name'] = options.package_name if options.r_text: deps_info['r_text'] = options.r_text if options.is_locale_resource: deps_info['is_locale_resource'] = True deps_info['resources_dirs'] = [] if options.resource_dirs: for gyp_list in options.resource_dirs: deps_info['resources_dirs'].extend(build_utils.ParseGnList(gyp_list)) if options.supports_android and options.type in ('android_apk', 'java_library'): # Lint all resources that are not already linted by a dependent library. owned_resource_dirs = set() owned_resource_zips = set() for c in all_resources_deps: # Always use resources_dirs in favour of resources_zips so that lint error # messages have paths that are closer to reality (and to avoid needing to # extract during lint). if c['resources_dirs']: owned_resource_dirs.update(c['resources_dirs']) else: owned_resource_zips.add(c['resources_zip']) for c in all_library_deps: if c['supports_android']: owned_resource_dirs.difference_update(c['owned_resources_dirs']) owned_resource_zips.difference_update(c['owned_resources_zips']) deps_info['owned_resources_dirs'] = list(owned_resource_dirs) deps_info['owned_resources_zips'] = list(owned_resource_zips) if options.type in ('android_resources','android_apk', 'resource_rewriter'): config['resources'] = {} config['resources']['dependency_zips'] = [ c['resources_zip'] for c in all_resources_deps] config['resources']['extra_package_names'] = [] config['resources']['extra_r_text_files'] = [] if options.type == 'android_apk' or options.type == 'resource_rewriter': config['resources']['extra_package_names'] = [ c['package_name'] for c in all_resources_deps if 'package_name' in c] config['resources']['extra_r_text_files'] = [ c['r_text'] for c in all_resources_deps if 'r_text' in c] if options.type in ['android_apk', 'deps_dex']: deps_dex_files = [c['dex_path'] for c in all_library_deps] if options.type in ('java_binary', 'java_library', 'android_apk'): javac_classpath = [c['jar_path'] for c in direct_library_deps] java_full_classpath = [c['jar_path'] for c in all_library_deps] if options.extra_classpath_jars: extra_jars = build_utils.ParseGnList(options.extra_classpath_jars) deps_info['extra_classpath_jars'] = extra_jars javac_classpath += extra_jars # The java code for an instrumentation test apk is assembled differently for # ProGuard vs. non-ProGuard. # # Without ProGuard: Each library's jar is dexed separately and then combined # into a single classes.dex. A test apk will include all dex files not already # present in the apk-under-test. At runtime all test code lives in the test # apk, and the program code lives in the apk-under-test. # # With ProGuard: Each library's .jar file is fed into ProGuard, which outputs # a single .jar, which is then dexed into a classes.dex. A test apk includes # all jar files from the program and the tests because having them separate # doesn't work with ProGuard's whole-program optimizations. Although the # apk-under-test still has all of its code in its classes.dex, none of it is # used at runtime because the copy of it within the test apk takes precidence. if options.type == 'android_apk' and options.tested_apk_config: tested_apk_config = GetDepConfig(options.tested_apk_config) expected_tested_package = tested_apk_config['package_name'] AndroidManifest(options.android_manifest).CheckInstrumentation( expected_tested_package) if options.proguard_enabled: # Add all tested classes to the test's classpath to ensure that the test's # java code is a superset of the tested apk's java code java_full_classpath += [ jar for jar in tested_apk_config['java']['full_classpath'] if jar not in java_full_classpath] if tested_apk_config['proguard_enabled']: assert options.proguard_enabled, ('proguard must be enabled for ' 'instrumentation apks if it\'s enabled for the tested apk.') # Include in the classpath classes that are added directly to the apk under # test (those that are not a part of a java_library). javac_classpath.append(tested_apk_config['jar_path']) java_full_classpath.append(tested_apk_config['jar_path']) # Exclude dex files from the test apk that exist within the apk under test. # TODO(agrieve): When proguard is enabled, this filtering logic happens # within proguard_util.py. Move the logic for the proguard case into # here as well. tested_apk_library_deps = tested_apk_deps.All('java_library') tested_apk_deps_dex_files = [c['dex_path'] for c in tested_apk_library_deps] deps_dex_files = [ p for p in deps_dex_files if not p in tested_apk_deps_dex_files] if options.type == 'android_apk': deps_info['proguard_enabled'] = options.proguard_enabled deps_info['proguard_info'] = options.proguard_info config['proguard'] = {} proguard_config = config['proguard'] proguard_config['input_paths'] = [options.jar_path] + java_full_classpath extra_jars = set() for c in all_library_deps: extra_jars.update(c.get('extra_classpath_jars', ())) proguard_config['lib_paths'] = list(extra_jars) # Dependencies for the final dex file of an apk or a 'deps_dex'. if options.type in ['android_apk', 'deps_dex']: config['final_dex'] = {} dex_config = config['final_dex'] dex_config['dependency_dex_files'] = deps_dex_files if options.type in ('java_binary', 'java_library', 'android_apk'): config['javac']['classpath'] = javac_classpath config['javac']['interface_classpath'] = [ _AsInterfaceJar(p) for p in javac_classpath] deps_info['java'] = { 'full_classpath': java_full_classpath } if options.type == 'android_apk': dependency_jars = [c['jar_path'] for c in all_library_deps] all_interface_jars = [ _AsInterfaceJar(p) for p in dependency_jars + [options.jar_path]] config['dist_jar'] = { 'dependency_jars': dependency_jars, 'all_interface_jars': all_interface_jars, } manifest = AndroidManifest(options.android_manifest) deps_info['package_name'] = manifest.GetPackageName() if not options.tested_apk_config and manifest.GetInstrumentation(): # This must then have instrumentation only for itself. manifest.CheckInstrumentation(manifest.GetPackageName()) library_paths = [] java_libraries_list = None runtime_deps_files = build_utils.ParseGnList( options.shared_libraries_runtime_deps or '[]') if runtime_deps_files: library_paths = _ExtractSharedLibsFromRuntimeDeps(runtime_deps_files) # Create a java literal array with the "base" library names: # e.g. libfoo.so -> foo java_libraries_list = ('{%s}' % ','.join( ['"%s"' % s[3:-3] for s in library_paths])) all_inputs.extend(runtime_deps_files) config['native'] = { 'libraries': library_paths, 'java_libraries_list': java_libraries_list, } config['assets'], config['uncompressed_assets'] = ( _MergeAssets(deps.All('android_assets'))) build_utils.WriteJson(config, options.build_config, only_if_changed=True) if options.depfile: build_utils.WriteDepfile(options.depfile, all_inputs)
def _ParseArgs(args): """Parses command line options. Returns: An options object as from argparse.ArgumentParser.parse_args() """ parser, input_opts, output_opts = resource_utils.ResourceArgsParser() input_opts.add_argument('--aapt2-path', required=True, help='Path to the Android aapt2 tool.') input_opts.add_argument('--android-manifest', required=True, help='AndroidManifest.xml path.') input_opts.add_argument( '--r-java-root-package-name', default='base', help='Short package name for this target\'s root R java file (ex. ' 'input of "base" would become gen.base_module). Defaults to "base".') group = input_opts.add_mutually_exclusive_group() group.add_argument( '--shared-resources', action='store_true', help='Make all resources in R.java non-final and allow the resource IDs ' 'to be reset to a different package index when the apk is loaded by ' 'another application at runtime.') group.add_argument( '--app-as-shared-lib', action='store_true', help='Same as --shared-resources, but also ensures all resource IDs are ' 'directly usable from the APK loaded as an application.') input_opts.add_argument( '--package-id', type=int, help='Decimal integer representing custom package ID for resources ' '(instead of 127==0x7f). Cannot be used with --shared-resources.') input_opts.add_argument( '--package-name', help='Package name that will be used to create R class.') input_opts.add_argument('--rename-manifest-package', help='Package name to force AAPT to use.') input_opts.add_argument( '--arsc-package-name', help='Package name to set in manifest of resources.arsc file. This is ' 'only used for apks under test.') input_opts.add_argument( '--shared-resources-allowlist', help='An R.txt file acting as a allowlist for resources that should be ' 'non-final and have their package ID changed at runtime in R.java. ' 'Implies and overrides --shared-resources.') input_opts.add_argument( '--shared-resources-allowlist-locales', default='[]', help= 'Optional GN-list of locales. If provided, all strings corresponding' ' to this locale list will be kept in the final output for the ' 'resources identified through --shared-resources-allowlist, even ' 'if --locale-allowlist is being used.') input_opts.add_argument( '--use-resource-ids-path', help='Use resource IDs generated by aapt --emit-ids.') input_opts.add_argument( '--extra-main-r-text-files', help= 'Additional R.txt files that will be added to the root R.java file, ' 'but not packaged in the generated resources.arsc. If these resources ' 'entries contain duplicate resources with the generated R.txt file, they ' 'must be identical.') input_opts.add_argument('--support-zh-hk', action='store_true', help='Use zh-rTW resources for zh-rHK.') input_opts.add_argument('--debuggable', action='store_true', help='Whether to add android:debuggable="true".') input_opts.add_argument('--version-code', help='Version code for apk.') input_opts.add_argument('--version-name', help='Version name for apk.') input_opts.add_argument('--min-sdk-version', required=True, help='android:minSdkVersion for APK.') input_opts.add_argument('--target-sdk-version', required=True, help="android:targetSdkVersion for APK.") input_opts.add_argument( '--max-sdk-version', help="android:maxSdkVersion expected in AndroidManifest.xml.") input_opts.add_argument('--manifest-package', help='Package name of the AndroidManifest.xml.') input_opts.add_argument( '--locale-allowlist', default='[]', help='GN list of languages to include. All other language configs will ' 'be stripped out. List may include a combination of Android locales ' 'or Chrome locales.') input_opts.add_argument( '--resource-exclusion-regex', default='', help='File-based filter for resources (applied before compiling)') input_opts.add_argument( '--resource-exclusion-exceptions', default='[]', help='GN list of globs that say which files to include even ' 'when --resource-exclusion-regex is set.') input_opts.add_argument( '--dependencies-res-zip-overlays', help='GN list with subset of --dependencies-res-zips to use overlay ' 'semantics for.') input_opts.add_argument( '--values-filter-rules', help='GN list of source_glob:regex for filtering resources after they ' 'are compiled. Use this to filter out entries within values/ files.') input_opts.add_argument('--png-to-webp', action='store_true', help='Convert png files to webp format.') input_opts.add_argument('--webp-binary', default='', help='Path to the cwebp binary.') input_opts.add_argument('--webp-cache-dir', help='The directory to store webp image cache.') input_opts.add_argument( '--no-xml-namespaces', action='store_true', help='Whether to strip xml namespaces from processed xml resources.') input_opts.add_argument( '--short-resource-paths', action='store_true', help='Whether to shorten resource paths inside the apk or module.') input_opts.add_argument( '--strip-resource-names', action='store_true', help= 'Whether to strip resource names from the resource table of the apk ' 'or module.') output_opts.add_argument('--arsc-path', help='Apk output for arsc format.') output_opts.add_argument('--proto-path', help='Apk output for proto format.') group = input_opts.add_mutually_exclusive_group() group.add_argument( '--optimized-arsc-path', help='Output for `aapt2 optimize` for arsc format (enables the step).') group.add_argument( '--optimized-proto-path', help='Output for `aapt2 optimize` for proto format (enables the step).' ) input_opts.add_argument( '--resources-config-paths', default='[]', help='GN list of paths to aapt2 resources config files.') output_opts.add_argument( '--info-path', help='Path to output info file for the partial apk.') output_opts.add_argument( '--srcjar-out', required=True, help='Path to srcjar to contain generated R.java.') output_opts.add_argument('--r-text-out', help='Path to store the generated R.txt file.') output_opts.add_argument('--proguard-file', help='Path to proguard.txt generated file.') output_opts.add_argument( '--proguard-file-main-dex', help='Path to proguard.txt generated file for main dex.') output_opts.add_argument('--emit-ids-out', help='Path to file produced by aapt2 --emit-ids.') output_opts.add_argument( '--resources-path-map-out-path', help='Path to file produced by aapt2 that maps original resource paths ' 'to shortened resource paths inside the apk or module.') input_opts.add_argument( '--is-bundle-module', action='store_true', help='Whether resources are being generated for a bundle module.') input_opts.add_argument( '--uses-split', help='Value to set uses-split to in the AndroidManifest.xml.') input_opts.add_argument( '--extra-verification-manifest', help='Path to AndroidManifest.xml which should be merged into base ' 'manifest when performing verification.') diff_utils.AddCommandLineFlags(parser) options = parser.parse_args(args) resource_utils.HandleCommonOptions(options) options.locale_allowlist = build_utils.ParseGnList( options.locale_allowlist) options.shared_resources_allowlist_locales = build_utils.ParseGnList( options.shared_resources_allowlist_locales) options.resource_exclusion_exceptions = build_utils.ParseGnList( options.resource_exclusion_exceptions) options.dependencies_res_zip_overlays = build_utils.ParseGnList( options.dependencies_res_zip_overlays) options.values_filter_rules = build_utils.ParseGnList( options.values_filter_rules) options.extra_main_r_text_files = build_utils.ParseGnList( options.extra_main_r_text_files) options.resources_config_paths = build_utils.ParseGnList( options.resources_config_paths) if options.optimized_proto_path and not options.proto_path: # We could write to a temp file, but it's simpler to require it. parser.error('--optimized-proto-path requires --proto-path') if not options.arsc_path and not options.proto_path: parser.error('One of --arsc-path or --proto-path is required.') if options.resources_path_map_out_path and not options.short_resource_paths: parser.error( '--resources-path-map-out-path requires --short-resource-paths') if options.package_id and options.shared_resources: parser.error( '--package-id and --shared-resources are mutually exclusive') return options
def _ParseOptions(): args = build_utils.ExpandFileArgs(sys.argv[1:]) parser = argparse.ArgumentParser() build_utils.AddDepfileOption(parser) parser.add_argument('--r8-path', required=True, help='Path to the R8.jar to use.') parser.add_argument('--desugar-jdk-libs-json', help='Path to desugar_jdk_libs.json.') parser.add_argument('--input-paths', action='append', required=True, help='GN-list of .jar files to optimize.') parser.add_argument('--desugar-jdk-libs-jar', help='Path to desugar_jdk_libs.jar.') parser.add_argument('--desugar-jdk-libs-configuration-jar', help='Path to desugar_jdk_libs_configuration.jar.') parser.add_argument('--output-path', help='Path to the generated .jar file.') parser.add_argument('--proguard-configs', action='append', required=True, help='GN-list of configuration files.') parser.add_argument('--apply-mapping', help='Path to ProGuard mapping to apply.') parser.add_argument('--mapping-output', required=True, help='Path for ProGuard to output mapping file to.') parser.add_argument( '--extra-mapping-output-paths', help='GN-list of additional paths to copy output mapping file to.') parser.add_argument('--classpath', action='append', help='GN-list of .jar files to include as libraries.') parser.add_argument('--main-dex-rules-path', action='append', help='Path to main dex rules for multidex.') parser.add_argument('--min-api', help='Minimum Android API level compatibility.') parser.add_argument('--enable-obfuscation', action='store_true', help='Minify symbol names') parser.add_argument('--verbose', '-v', action='store_true', help='Print all ProGuard output') parser.add_argument('--repackage-classes', help='Package all optimized classes are put in.') parser.add_argument( '--disable-outlining', action='store_true', help='Disable the outlining optimization provided by R8.') parser.add_argument( '--disable-checks', action='store_true', help='Disable -checkdiscard directives and missing symbols check') parser.add_argument('--sourcefile', help='Value for source file attribute') parser.add_argument( '--force-enable-assertions', action='store_true', help='Forcefully enable javac generated assertion code.') parser.add_argument( '--feature-jars', action='append', help='GN list of path to jars which comprise the corresponding feature.' ) parser.add_argument( '--dex-dest', action='append', dest='dex_dests', help='Destination for dex file of the corresponding feature.') parser.add_argument('--feature-name', action='append', dest='feature_names', help='The name of the feature module.') parser.add_argument( '--uses-split', action='append', help='List of name pairs separated by : mapping a feature module to a ' 'dependent feature module.') parser.add_argument( '--keep-rules-targets-regex', metavar='KEEP_RULES_REGEX', help='If passed outputs keep rules for references from all other inputs ' 'to the subset of inputs that satisfy the KEEP_RULES_REGEX.') parser.add_argument( '--keep-rules-output-path', help='Output path to the keep rules for references to the ' '--keep-rules-targets-regex inputs from the rest of the inputs.') parser.add_argument('--warnings-as-errors', action='store_true', help='Treat all warnings as errors.') parser.add_argument('--show-desugar-default-interface-warnings', action='store_true', help='Enable desugaring warnings.') parser.add_argument('--dump-inputs', action='store_true', help='Use when filing R8 bugs to capture inputs.' ' Stores inputs to r8inputs.zip') parser.add_argument( '--stamp', help='File to touch upon success. Mutually exclusive with --output-path' ) parser.add_argument( '--desugared-library-keep-rule-output', help='Path to desugared library keep rule output file.') diff_utils.AddCommandLineFlags(parser) options = parser.parse_args(args) if options.feature_names: if options.output_path: parser.error('Feature splits cannot specify an output in GN.') if not options.actual_file and not options.stamp: parser.error('Feature splits require a stamp file as output.') elif not options.output_path: parser.error('Output path required when feature splits aren\'t used') if bool(options.keep_rules_targets_regex) != bool( options.keep_rules_output_path): raise Exception('You must path both --keep-rules-targets-regex and ' '--keep-rules-output-path') options.classpath = build_utils.ParseGnList(options.classpath) options.proguard_configs = build_utils.ParseGnList( options.proguard_configs) options.input_paths = build_utils.ParseGnList(options.input_paths) options.extra_mapping_output_paths = build_utils.ParseGnList( options.extra_mapping_output_paths) if options.feature_names: if 'base' not in options.feature_names: parser.error( '"base" feature required when feature arguments are used.') if len(options.feature_names) != len(options.feature_jars) or len( options.feature_names) != len(options.dex_dests): parser.error('Invalid feature argument lengths.') options.feature_jars = [ build_utils.ParseGnList(x) for x in options.feature_jars ] split_map = {} if options.uses_split: for split_pair in options.uses_split: child, parent = split_pair.split(':') for name in (child, parent): if name not in options.feature_names: parser.error( '"%s" referenced in --uses-split not present.' % name) split_map[child] = parent options.uses_split = split_map return options
def _ParseArgs(args): """Parses command line options. Returns: An options object as from argparse.ArgumentParser.parse_args() """ parser, input_opts, output_opts = resource_utils.ResourceArgsParser() input_opts.add_argument('--aapt2-path', required=True, help='Path to the Android aapt2 tool.') input_opts.add_argument('--android-manifest', required=True, help='AndroidManifest.xml path') input_opts.add_argument( '--shared-resources', action='store_true', help='Make all resources in R.java non-final and allow the resource IDs ' 'to be reset to a different package index when the apk is loaded by ' 'another application at runtime.') input_opts.add_argument( '--app-as-shared-lib', action='store_true', help='Same as --shared-resources, but also ensures all resource IDs are ' 'directly usable from the APK loaded as an application.') input_opts.add_argument( '--package-id', help='Custom package ID for resources (instead of 0x7f). Cannot be used ' 'with --shared-resources.') input_opts.add_argument( '--package-name-to-id-mapping', help= 'List containing mapping from package name to package IDs that will ' 'be assigned.') input_opts.add_argument( '--package-name', help='Package name that will be used to determine package ID.') input_opts.add_argument('--arsc-package-name', help='Package name to use for resources.arsc file') input_opts.add_argument( '--shared-resources-whitelist', help='An R.txt file acting as a whitelist for resources that should be ' 'non-final and have their package ID changed at runtime in R.java. ' 'Implies and overrides --shared-resources.') input_opts.add_argument( '--shared-resources-whitelist-locales', default='[]', help= 'Optional GN-list of locales. If provided, all strings corresponding' ' to this locale list will be kept in the final output for the ' 'resources identified through --shared-resources-whitelist, even ' 'if --locale-whitelist is being used.') input_opts.add_argument( '--use-resource-ids-path', help='Use resource IDs generated by aapt --emit-ids') input_opts.add_argument( '--proto-format', action='store_true', help='Compile resources to protocol buffer format.') input_opts.add_argument('--support-zh-hk', action='store_true', help='Use zh-rTW resources for zh-rHK.') input_opts.add_argument('--debuggable', action='store_true', help='Whether to add android:debuggable="true"') input_opts.add_argument('--version-code', help='Version code for apk.') input_opts.add_argument('--version-name', help='Version name for apk.') input_opts.add_argument( '--no-compress', help='disables compression for the given comma-separated list of ' 'extensions') input_opts.add_argument( '--locale-whitelist', default='[]', help='GN list of languages to include. All other language configs will ' 'be stripped out. List may include a combination of Android locales ' 'or Chrome locales.') input_opts.add_argument('--resource-blacklist-regex', default='', help='Do not include matching drawables.') input_opts.add_argument( '--resource-blacklist-exceptions', default='[]', help= 'GN list of globs that say which blacklisted images to include even ' 'when --resource-blacklist-regex is set.') input_opts.add_argument('--png-to-webp', action='store_true', help='Convert png files to webp format.') input_opts.add_argument('--webp-binary', default='', help='Path to the cwebp binary.') input_opts.add_argument( '--no-xml-namespaces', action='store_true', help='Whether to strip xml namespaces from processed ' 'xml resources') input_opts.add_argument('--resources-config-path', help='Path to aapt2 resources config file.') input_opts.add_argument( '--optimized-resources-path', help='Output for `aapt2 optimize` (also enables the step).') output_opts.add_argument('--apk-path', required=True, help='Path to output (partial) apk.') output_opts.add_argument( '--apk-info-path', required=True, help='Path to output info file for the partial apk.') output_opts.add_argument( '--srcjar-out', help='Path to srcjar to contain generated R.java.') output_opts.add_argument('--r-text-out', help='Path to store the generated R.txt file.') output_opts.add_argument('--proguard-file', help='Path to proguard.txt generated file') output_opts.add_argument( '--proguard-file-main-dex', help='Path to proguard.txt generated file for main dex') output_opts.add_argument( '--emit-ids-out', help= 'Path to file produced by aapt2 --emit-ids (for use with --stable-ids)' ) options = parser.parse_args(args) resource_utils.HandleCommonOptions(options) options.locale_whitelist = build_utils.ParseGnList( options.locale_whitelist) options.shared_resources_whitelist_locales = build_utils.ParseGnList( options.shared_resources_whitelist_locales) options.resource_blacklist_exceptions = build_utils.ParseGnList( options.resource_blacklist_exceptions) if options.shared_resources and options.app_as_shared_lib: raise Exception( 'Only one of --app-as-shared-lib or --shared-resources ' 'can be used.') if options.package_name_to_id_mapping: package_names_list = build_utils.ParseGnList( options.package_name_to_id_mapping) options.package_name_to_id_mapping = _ListToDictionary( package_names_list, '=') return options
def _ParseArgs(args): args = build_utils.ExpandFileArgs(args) parser = argparse.ArgumentParser() build_utils.AddDepfileOption(parser) parser.add_argument('--output', required=True, help='Dex output path.') parser.add_argument('--class-inputs', action='append', help='GN-list of .jars with .class files.') parser.add_argument( '--class-inputs-filearg', action='append', help='GN-list of .jars with .class files (added to depfile).') parser.add_argument('--dex-inputs', action='append', help='GN-list of .jars with .dex files.') parser.add_argument( '--dex-inputs-filearg', action='append', help='GN-list of .jars with .dex files (added to depfile).') parser.add_argument( '--incremental-dir', help='Path of directory to put intermediate dex files.') parser.add_argument( '--main-dex-list-path', help='File containing a list of the classes to include in the main dex.' ) parser.add_argument('--multi-dex', action='store_true', help='Allow multiple dex files within output.') parser.add_argument('--r8-jar-path', required=True, help='Path to R8 jar.') parser.add_argument('--desugar', action='store_true') parser.add_argument('--bootclasspath', action='append', help='GN-list of bootclasspath. Needed for --desugar') parser.add_argument('--classpath', action='append', help='GN-list of full classpath. Needed for --desugar') parser.add_argument( '--release', action='store_true', help='Run D8 in release mode. Release mode maximises main dex and ' 'deletes non-essential line number information (vs debug which minimizes ' 'main dex and keeps all line number information, and then some.') parser.add_argument('--min-api', help='Minimum Android API level compatibility.') group = parser.add_argument_group('Dexlayout') group.add_argument( '--dexlayout-profile', help=('Text profile for dexlayout. If present, a dexlayout ' 'pass will happen')) group.add_argument( '--profman-path', help=( 'Path to ART profman binary. There should be a lib/ directory at ' 'the same path with shared libraries (shared with dexlayout).')) group.add_argument( '--dexlayout-path', help=( 'Path to ART dexlayout binary. There should be a lib/ directory at ' 'the same path with shared libraries (shared with dexlayout).')) group.add_argument('--dexdump-path', help='Path to dexdump binary.') group.add_argument( '--proguard-mapping-path', help=( 'Path to proguard map from obfuscated symbols in the jar to ' 'unobfuscated symbols present in the code. If not present, the jar ' 'is assumed not to be obfuscated.')) parser.add_argument( '--force-enable-assertions', action='store_true', help='Forcefully enable javac generated assertion code.') options = parser.parse_args(args) if options.dexlayout_profile: build_utils.CheckOptions(options, parser, required=('profman_path', 'dexlayout_path', 'dexdump_path')) elif options.proguard_mapping_path is not None: parser.error('Unexpected proguard mapping without dexlayout') if options.main_dex_list_path and not options.multi_dex: parser.error( '--main-dex-list-path is unused if multidex is not enabled') options.class_inputs = build_utils.ParseGnList(options.class_inputs) options.class_inputs_filearg = build_utils.ParseGnList( options.class_inputs_filearg) options.bootclasspath = build_utils.ParseGnList(options.bootclasspath) options.classpath = build_utils.ParseGnList(options.classpath) options.dex_inputs = build_utils.ParseGnList(options.dex_inputs) options.dex_inputs_filearg = build_utils.ParseGnList( options.dex_inputs_filearg) return options
def main(): parser = argparse.ArgumentParser() parser.add_argument('--inputs', required=True, help='GN-list of template files to process.') parser.add_argument('--includes', default='', help="GN-list of files that get {% include %}'ed.") parser.add_argument('--output', help='The output file to generate. Valid ' 'only if there is a single input.') parser.add_argument('--outputs-zip', help='A zip file for the processed ' 'templates. Required if there are multiple inputs.') parser.add_argument('--inputs-base-dir', help='A common ancestor directory ' 'of the inputs. Each output\'s path in the output zip ' 'will match the relative path from INPUTS_BASE_DIR to ' 'the input. Required if --output-zip is given.') parser.add_argument( '--loader-base-dir', help='Base path used by the ' 'template loader. Must be a common ancestor directory of ' 'the inputs. Defaults to DIR_SOURCE_ROOT.', default=host_paths.DIR_SOURCE_ROOT) parser.add_argument('--variables', help='Variables to be made available in ' 'the template processing environment, as a GYP list ' '(e.g. --variables "channel=beta mstone=39")', default='') build_utils.AddDepfileOption(parser) options = parser.parse_args() inputs = build_utils.ParseGnList(options.inputs) includes = build_utils.ParseGnList(options.includes) if (options.output is None) == (options.outputs_zip is None): parser.error('Exactly one of --output and --output-zip must be given') if options.output and len(inputs) != 1: parser.error('--output cannot be used with multiple inputs') if options.outputs_zip and not options.inputs_base_dir: parser.error( '--inputs-base-dir must be given when --output-zip is used') variables = _ParseVariables(options.variables, parser.error) processor = JinjaProcessor(options.loader_base_dir, variables=variables) if options.output: _ProcessFile(processor, inputs[0], options.output) else: _ProcessFiles(processor, inputs, options.inputs_base_dir, options.outputs_zip) if options.depfile: output = options.output or options.outputs_zip all_inputs = set(processor.GetLoadedTemplates()) all_inputs.difference_update(inputs) all_inputs.difference_update(includes) if all_inputs: # TODO(agrieve): Change this to an exception once downstream violations # are fixed. https://crbug.com/843562 print('Found files not listed via --includes:\n' + '\n'.join(sorted(all_inputs))) build_utils.WriteDepfile(options.depfile, output)
def _ParseArgs(argv): parser = argparse.ArgumentParser() build_utils.AddDepfileOption(parser) parser.add_argument('--target-name', help='Fully qualified GN target name.') parser.add_argument('--skip-build-server', action='store_true', help='Avoid using the build server.') parser.add_argument('--lint-binary-path', required=True, help='Path to lint executable.') parser.add_argument('--backported-methods', help='Path to backported methods file created by R8.') parser.add_argument( '--cache-dir', required=True, help='Path to the directory in which the android cache ' 'directory tree should be stored.') parser.add_argument('--config-path', help='Path to lint suppressions file.') parser.add_argument('--lint-gen-dir', required=True, help='Path to store generated xml files.') parser.add_argument('--stamp', help='Path to stamp upon success.') parser.add_argument('--android-sdk-version', help='Version (API level) of the Android SDK used for ' 'building.') parser.add_argument('--min-sdk-version', required=True, help='Minimal SDK version to lint against.') parser.add_argument('--android-sdk-root', required=True, help='Lint needs an explicit path to the android sdk.') parser.add_argument( '--testonly', action='store_true', help='If set, some checks like UnusedResources will be ' 'disabled since they are not helpful for test ' 'targets.') parser.add_argument( '--create-cache', action='store_true', help='Whether this invocation is just warming the cache.') parser.add_argument('--warnings-as-errors', action='store_true', help='Treat all warnings as errors.') parser.add_argument('--java-sources', help='File containing a list of java sources files.') parser.add_argument('--aars', help='GN list of included aars.') parser.add_argument('--srcjars', help='GN list of included srcjars.') parser.add_argument('--manifest-path', help='Path to original AndroidManifest.xml') parser.add_argument('--extra-manifest-paths', action='append', help='GYP-list of manifest paths to merge into the ' 'original AndroidManifest.xml') parser.add_argument('--resource-sources', default=[], action='append', help='GYP-list of resource sources files, similar to ' 'java sources files, but for resource files.') parser.add_argument( '--resource-zips', default=[], action='append', help='GYP-list of resource zips, zip files of generated ' 'resource files.') parser.add_argument('--classpath', help='List of jars to add to the classpath.') parser.add_argument( '--baseline', help='Baseline file to ignore existing errors and fail ' 'on new errors.') args = parser.parse_args(build_utils.ExpandFileArgs(argv)) args.java_sources = build_utils.ParseGnList(args.java_sources) args.aars = build_utils.ParseGnList(args.aars) args.srcjars = build_utils.ParseGnList(args.srcjars) args.resource_sources = build_utils.ParseGnList(args.resource_sources) args.extra_manifest_paths = build_utils.ParseGnList( args.extra_manifest_paths) args.resource_zips = build_utils.ParseGnList(args.resource_zips) args.classpath = build_utils.ParseGnList(args.classpath) return args
def main(args): args = build_utils.ExpandFileArgs(args) parser = argparse.ArgumentParser() build_utils.AddDepfileOption(parser) parser.add_argument('--output', required=True, help='Path to output aar.') parser.add_argument('--jars', required=True, help='GN list of jar inputs.') parser.add_argument('--dependencies-res-zips', required=True, help='GN list of resource zips') parser.add_argument('--r-text-files', required=True, help='GN list of R.txt files to merge') parser.add_argument('--proguard-configs', required=True, help='GN list of ProGuard flag files to merge.') parser.add_argument('--android-manifest', help='Path to AndroidManifest.xml to include.', default=os.path.join(_ANDROID_BUILD_DIR, 'AndroidManifest.xml')) parser.add_argument('--native-libraries', default='', help='GN list of native libraries. If non-empty then ' 'ABI must be specified.') parser.add_argument('--abi', help='ABI (e.g. armeabi-v7a) for native libraries.') parser.add_argument('--jar-excluded-globs', help='GN-list of globs for paths to exclude in jar.') parser.add_argument('--jar-included-globs', help='GN-list of globs for paths to include in jar.') options = parser.parse_args(args) if options.native_libraries and not options.abi: parser.error('You must provide --abi if you have native libs') options.jars = build_utils.ParseGnList(options.jars) options.dependencies_res_zips = build_utils.ParseGnList( options.dependencies_res_zips) options.r_text_files = build_utils.ParseGnList(options.r_text_files) options.proguard_configs = build_utils.ParseGnList( options.proguard_configs) options.native_libraries = build_utils.ParseGnList( options.native_libraries) options.jar_excluded_globs = build_utils.ParseGnList( options.jar_excluded_globs) options.jar_included_globs = build_utils.ParseGnList( options.jar_included_globs) with tempfile.NamedTemporaryFile(delete=False) as staging_file: try: with zipfile.ZipFile(staging_file.name, 'w') as z: build_utils.AddToZipHermetic(z, 'AndroidManifest.xml', src_path=options.android_manifest) path_transform = CreatePathTransform( options.jar_excluded_globs, options.jar_included_globs, []) with tempfile.NamedTemporaryFile() as jar_file: build_utils.MergeZips(jar_file.name, options.jars, path_transform=path_transform) build_utils.AddToZipHermetic(z, 'classes.jar', src_path=jar_file.name) build_utils.AddToZipHermetic(z, 'R.txt', data=_MergeRTxt( options.r_text_files)) build_utils.AddToZipHermetic(z, 'public.txt', data='') if options.proguard_configs: build_utils.AddToZipHermetic(z, 'proguard.txt', data=_MergeProguardConfigs( options.proguard_configs)) _AddResources(z, options.dependencies_res_zips) for native_library in options.native_libraries: libname = os.path.basename(native_library) build_utils.AddToZipHermetic(z, os.path.join( 'jni', options.abi, libname), src_path=native_library) except: os.unlink(staging_file.name) raise shutil.move(staging_file.name, options.output) if options.depfile: all_inputs = (options.jars + options.dependencies_res_zips + options.r_text_files + options.proguard_configs) build_utils.WriteDepfile(options.depfile, options.output, all_inputs, add_pydeps=False)
def main(argv): argv = build_utils.ExpandFileArgs(argv) parser = argparse.ArgumentParser(description=__doc__) build_utils.AddDepfileOption(parser) parser.add_argument('--build-vars', help='Path to GN build vars file', required=True) parser.add_argument('--root-manifest', help='Root manifest which to merge into', required=True) parser.add_argument('--output', help='Output manifest path', required=True) parser.add_argument('--extras', help='GN list of additional manifest to merge') parser.add_argument('--min-sdk-version', required=True, help='android:minSdkVersion for merging.') parser.add_argument('--target-sdk-version', required=True, help='android:targetSdkVersion for merging.') parser.add_argument('--max-sdk-version', help='android:maxSdkVersion for merging.') parser.add_argument('--manifest-package', help='Package name of the merged AndroidManifest.xml.') args = parser.parse_args(argv) classpath = _BuildManifestMergerClasspath( build_utils.ReadBuildVars(args.build_vars)) with build_utils.AtomicOutput(args.output) as output: cmd = [ build_utils.JAVA_PATH, '-cp', classpath, _MANIFEST_MERGER_MAIN_CLASS, '--out', output.name, '--property', 'MIN_SDK_VERSION=' + args.min_sdk_version, '--property', 'TARGET_SDK_VERSION=' + args.target_sdk_version, ] if args.max_sdk_version: cmd += [ '--property', 'MAX_SDK_VERSION=' + args.max_sdk_version, ] extras = build_utils.ParseGnList(args.extras) if extras: cmd += ['--libs', ':'.join(extras)] with _ProcessManifest(args.root_manifest, args.min_sdk_version, args.target_sdk_version, args.max_sdk_version, args.manifest_package) as tup: root_manifest, package = tup cmd += [ '--main', root_manifest, '--property', 'PACKAGE=' + package, ] build_utils.CheckOutput( cmd, # https://issuetracker.google.com/issues/63514300: # The merger doesn't set a nonzero exit code for failures. fail_func=lambda returncode, stderr: returncode != 0 or build_utils.IsTimeStale(output.name, [root_manifest] + extras)) # Check for correct output. _, manifest, _ = manifest_utils.ParseManifest(output.name) manifest_utils.AssertUsesSdk(manifest, args.min_sdk_version, args.target_sdk_version) manifest_utils.AssertPackage(manifest, package) if args.depfile: inputs = extras + classpath.split(':') build_utils.WriteDepfile(args.depfile, args.output, inputs=inputs, add_pydeps=False)
def main(args): parser = argparse.ArgumentParser() parser.add_argument('--script-output-path', help='Output path for executable script.') parser.add_argument('--depfile', help='Path to the depfile. This must be specified as ' "the action's first output.") parser.add_argument('--test-runner-path', help='Path to test_runner.py (optional).') # We need to intercept any test runner path arguments and make all # of the paths relative to the output script directory. group = parser.add_argument_group('Test runner path arguments.') group.add_argument('--additional-apk', action='append', dest='additional_apks', default=[]) group.add_argument('--additional-apk-list') group.add_argument('--additional-apk-incremental', action='append', dest='additional_apks_incremental', default=[]) group.add_argument('--apk-under-test') group.add_argument('--apk-under-test-incremental-install-json') group.add_argument('--executable-dist-dir') group.add_argument('--isolate-file-path') group.add_argument('--output-directory') group.add_argument('--runtime-deps-path') group.add_argument('--test-apk') group.add_argument('--test-jar') group.add_argument('--test-apk-incremental-install-json') group.add_argument('--coverage-dir') group.add_argument('--android-manifest-path') group.add_argument('--resource-zips') group.add_argument('--robolectric-runtime-deps-dir') group.add_argument('--non-native-packed-relocations') args, test_runner_args = parser.parse_known_args( build_utils.ExpandFileArgs(args)) def RelativizePathToScript(path): """Returns the path relative to the output script directory.""" return os.path.relpath(path, os.path.dirname(args.script_output_path)) test_runner_path = args.test_runner_path or os.path.join( os.path.dirname(__file__), os.path.pardir, 'test_runner.py') test_runner_path = RelativizePathToScript(test_runner_path) test_runner_path_args = [] if 'True' == args.non_native_packed_relocations: test_runner_args.append('--non-native-packed-relocations') if args.additional_apk_list: args.additional_apks.extend( build_utils.ParseGnList(args.additional_apk_list)) if args.additional_apks: test_runner_path_args.extend( ('--additional-apk', RelativizePathToScript(a)) for a in args.additional_apks) if args.additional_apks_incremental: bad_additional_apks = [ a for a in args.additional_apks_incremental if a != 'None' ] if bad_additional_apks: raise Exception( _GenerateAdditionalApksErrorString(bad_additional_apks)) if args.apk_under_test: test_runner_path_args.append( ('--apk-under-test', RelativizePathToScript(args.apk_under_test))) if args.apk_under_test_incremental_install_json: test_runner_path_args.append( ('--apk-under-test-incremental-install-json', RelativizePathToScript( args.apk_under_test_incremental_install_json))) if args.executable_dist_dir: test_runner_path_args.append( ('--executable-dist-dir', RelativizePathToScript(args.executable_dist_dir))) if args.isolate_file_path: test_runner_path_args.append( ('--isolate-file-path', RelativizePathToScript(args.isolate_file_path))) if args.output_directory: test_runner_path_args.append( ('--output-directory', RelativizePathToScript(args.output_directory))) if args.runtime_deps_path: test_runner_path_args.append( ('--runtime-deps-path', RelativizePathToScript(args.runtime_deps_path))) if args.test_apk: test_runner_path_args.append( ('--test-apk', RelativizePathToScript(args.test_apk))) if args.test_jar: test_runner_path_args.append( ('--test-jar', RelativizePathToScript(args.test_jar))) if args.test_apk_incremental_install_json: test_runner_path_args.append( ('--test-apk-incremental-install-json', RelativizePathToScript(args.test_apk_incremental_install_json))) if args.coverage_dir: test_runner_path_args.append( ('--coverage-dir', RelativizePathToScript(args.coverage_dir))) if args.android_manifest_path: test_runner_path_args.append( ('--android-manifest-path', RelativizePathToScript(args.android_manifest_path))) if args.resource_zips: test_runner_path_args.extend( ('--resource-zip', RelativizePathToScript(r)) for r in build_utils.ParseGnList(args.resource_zips)) if args.robolectric_runtime_deps_dir: test_runner_path_args.append( ('--robolectric-runtime-deps-dir', RelativizePathToScript(args.robolectric_runtime_deps_dir))) with open(args.script_output_path, 'w') as script: script.write( SCRIPT_TEMPLATE.format( test_runner_path=str(test_runner_path), test_runner_args=str(test_runner_args), test_runner_path_args=str(test_runner_path_args))) os.chmod(args.script_output_path, 0750) if args.depfile: build_utils.WriteDepfile(args.depfile, args.script_output_path)
def _ParseOptions(argv): parser = optparse.OptionParser() build_utils.AddDepfileOption(parser) parser.add_option('--target-name', help='Fully qualified GN target name.') parser.add_option('--skip-build-server', action='store_true', help='Avoid using the build server.') parser.add_option('--java-srcjars', action='append', default=[], help='List of srcjars to include in compilation.') parser.add_option( '--generated-dir', help='Subdirectory within target_gen_dir to place extracted srcjars and ' 'annotation processor output for codesearch to find.') parser.add_option( '--bootclasspath', action='append', default=[], help='Boot classpath for javac. If this is specified multiple times, ' 'they will all be appended to construct the classpath.') parser.add_option( '--java-version', help= 'Java language version to use in -source and -target args to javac.') parser.add_option('--classpath', action='append', help='Classpath to use.') parser.add_option( '--processorpath', action='append', help='GN list of jars that comprise the classpath used for Annotation ' 'Processors.') parser.add_option( '--processor-arg', dest='processor_args', action='append', help='key=value arguments for the annotation processors.') parser.add_option( '--additional-jar-file', dest='additional_jar_files', action='append', help= 'Additional files to package into jar. By default, only Java .class ' 'files are packaged into the jar. Files should be specified in ' 'format <filename>:<path to be placed in jar>.') parser.add_option( '--jar-info-exclude-globs', help='GN list of exclude globs to filter from generated .info files.') parser.add_option( '--chromium-code', type='int', help='Whether code being compiled should be built with stricter ' 'warnings for chromium code.') parser.add_option('--gomacc-path', help='When set, prefix javac command with gomacc') parser.add_option('--errorprone-path', help='Use the Errorprone compiler at this path.') parser.add_option('--enable-errorprone', action='store_true', help='Enable errorprone checks') parser.add_option('--warnings-as-errors', action='store_true', help='Treat all warnings as errors.') parser.add_option('--jar-path', help='Jar output path.') parser.add_option('--javac-arg', action='append', default=[], help='Additional arguments to pass to javac.') parser.add_option( '--enable-kythe-annotations', action='store_true', help='Enable generation of Kythe kzip, used for codesearch. Ensure ' 'proper environment variables are set before using this flag.') parser.add_option( '--header-jar', help='This is the header jar for the current target that contains ' 'META-INF/services/* files to be included in the output jar.') options, args = parser.parse_args(argv) build_utils.CheckOptions(options, parser, required=('jar_path', )) options.bootclasspath = build_utils.ParseGnList(options.bootclasspath) options.classpath = build_utils.ParseGnList(options.classpath) options.processorpath = build_utils.ParseGnList(options.processorpath) options.java_srcjars = build_utils.ParseGnList(options.java_srcjars) options.jar_info_exclude_globs = build_utils.ParseGnList( options.jar_info_exclude_globs) additional_jar_files = [] for arg in options.additional_jar_files or []: filepath, jar_filepath = arg.split(':') additional_jar_files.append((filepath, jar_filepath)) options.additional_jar_files = additional_jar_files java_files = [] for arg in args: # Interpret a path prefixed with @ as a file containing a list of sources. if arg.startswith('@'): java_files.extend(build_utils.ReadSourcesList(arg[1:])) else: java_files.append(arg) return options, java_files
def main(args): args = build_utils.ExpandFileArgs(args) parser = argparse.ArgumentParser() parser.add_argument('--script-output-path', required=True, help='Output path for executable script.') parser.add_argument('--bundle-path', required=True) parser.add_argument('--bundle-apks-path', required=True) parser.add_argument( '--additional-apk-path', action='append', dest='additional_apk_paths', default=[], help='Paths to APKs to be installed prior to --apk-path.') parser.add_argument('--package-name', required=True) parser.add_argument('--aapt2-path', required=True) parser.add_argument('--keystore-path', required=True) parser.add_argument('--keystore-password', required=True) parser.add_argument('--key-name', required=True) parser.add_argument('--command-line-flags-file') parser.add_argument('--proguard-mapping-path') parser.add_argument('--target-cpu') parser.add_argument('--system-image-locales') parser.add_argument('--default-modules', nargs='*', default=[]) args = parser.parse_args(args) def relativize(path): """Returns the path relative to the output script directory.""" if path is None: return path return os.path.relpath(path, os.path.dirname(args.script_output_path)) wrapped_script_dir = os.path.join(os.path.dirname(__file__), os.path.pardir) wrapped_script_dir = relativize(wrapped_script_dir) with open(args.script_output_path, 'w') as script: script_dict = { 'WRAPPED_SCRIPT_DIR': repr(wrapped_script_dir), 'OUTPUT_DIR': repr(relativize('.')), 'BUNDLE_PATH': repr(relativize(args.bundle_path)), 'BUNDLE_APKS_PATH': repr(relativize(args.bundle_apks_path)), 'ADDITIONAL_APK_PATHS': [relativize(p) for p in args.additional_apk_paths], 'PACKAGE_NAME': repr(args.package_name), 'AAPT2_PATH': repr(relativize(args.aapt2_path)), 'KEYSTORE_PATH': repr(relativize(args.keystore_path)), 'KEYSTORE_PASSWORD': repr(args.keystore_password), 'KEY_NAME': repr(args.key_name), 'MAPPING_PATH': repr(relativize(args.proguard_mapping_path)), 'FLAGS_FILE': repr(args.command_line_flags_file), 'TARGET_CPU': repr(args.target_cpu), 'SYSTEM_IMAGE_LOCALES': repr(build_utils.ParseGnList(args.system_image_locales)), 'DEFAULT_MODULES': repr(args.default_modules), } script.write(SCRIPT_TEMPLATE.substitute(script_dict)) os.chmod(args.script_output_path, 0750) return 0
def _ParseArgs(args): """Parses command line options. Returns: An options object as from argparse.ArgumentParser.parse_args() """ parser, input_opts, output_opts = resource_utils.ResourceArgsParser() input_opts.add_argument('--android-manifest', required=True, help='AndroidManifest.xml path') input_opts.add_argument( '--shared-resources', action='store_true', help='Make all resources in R.java non-final and allow the resource IDs ' 'to be reset to a different package index when the apk is loaded by ' 'another application at runtime.') input_opts.add_argument( '--app-as-shared-lib', action='store_true', help='Same as --shared-resources, but also ensures all resource IDs are ' 'directly usable from the APK loaded as an application.') input_opts.add_argument( '--shared-resources-whitelist', help='An R.txt file acting as a whitelist for resources that should be ' 'non-final and have their package ID changed at runtime in R.java. ' 'Implies and overrides --shared-resources.') input_opts.add_argument( '--proto-format', action='store_true', help='Compile resources to protocol buffer format.') input_opts.add_argument('--support-zh-hk', action='store_true', help='Use zh-rTW resources for zh-rHK.') input_opts.add_argument('--debuggable', action='store_true', help='Whether to add android:debuggable="true"') input_opts.add_argument('--version-code', help='Version code for apk.') input_opts.add_argument('--version-name', help='Version name for apk.') input_opts.add_argument( '--no-compress', help='disables compression for the given comma-separated list of ' 'extensions') input_opts.add_argument( '--locale-whitelist', default='[]', help='GN list of languages to include. All other language configs will ' 'be stripped out. List may include a combination of Android locales ' 'or Chrome locales.') input_opts.add_argument('--exclude-xxxhdpi', action='store_true', help='Do not include xxxhdpi drawables.') input_opts.add_argument( '--xxxhdpi-whitelist', default='[]', help='GN list of globs that say which xxxhdpi images to include even ' 'when --exclude-xxxhdpi is set.') input_opts.add_argument('--png-to-webp', action='store_true', help='Convert png files to webp format.') input_opts.add_argument('--webp-binary', default='', help='Path to the cwebp binary.') input_opts.add_argument( '--no-xml-namespaces', action='store_true', help='Whether to strip xml namespaces from processed ' 'xml resources') input_opts.add_argument( '--check-resources-pkg-id', type=_PackageIdArgument, help='Check the package ID of the generated resources table. ' 'Value must be integer in [0..127] range.') output_opts.add_argument('--apk-path', required=True, help='Path to output (partial) apk.') output_opts.add_argument( '--apk-info-path', required=True, help='Path to output info file for the partial apk.') output_opts.add_argument( '--srcjar-out', help='Path to srcjar to contain generated R.java.') output_opts.add_argument('--r-text-out', help='Path to store the generated R.txt file.') output_opts.add_argument('--proguard-file', help='Path to proguard.txt generated file') output_opts.add_argument( '--proguard-file-main-dex', help='Path to proguard.txt generated file for main dex') options = parser.parse_args(args) resource_utils.HandleCommonOptions(options) options.locale_whitelist = build_utils.ParseGnList( options.locale_whitelist) options.xxxhdpi_whitelist = build_utils.ParseGnList( options.xxxhdpi_whitelist) if options.check_resources_pkg_id is not None: if options.check_resources_pkg_id < 0: raise Exception( 'Package resource id should be integer in [0..127] range.') if options.shared_resources and options.app_as_shared_lib: raise Exception( 'Only one of --app-as-shared-lib or --shared-resources ' 'can be used.') return options
def _ParseArgs(args): parser = argparse.ArgumentParser() build_utils.AddDepfileOption(parser) parser.add_argument( '--assets', help='GYP-list of files to add as assets in the form ' '"srcPath:zipPath", where ":zipPath" is optional.') parser.add_argument( '--java-resources', help='GYP-list of java_resources JARs to include.') parser.add_argument('--write-asset-list', action='store_true', help='Whether to create an assets/assets_list file.') parser.add_argument( '--uncompressed-assets', help='Same as --assets, except disables compression.') parser.add_argument('--resource-apk', help='An .ap_ file built using aapt', required=True) parser.add_argument('--output-apk', help='Path to the output file', required=True) parser.add_argument('--format', choices=['apk', 'bundle-module'], default='apk', help='Specify output format.') parser.add_argument('--dex-file', help='Path to the classes.dex to use') parser.add_argument( '--jdk-libs-dex-file', help='Path to classes.dex created by dex_jdk_libs.py') parser.add_argument('--uncompress-dex', action='store_true', help='Store .dex files uncompressed in the APK') parser.add_argument('--native-libs', action='append', help='GYP-list of native libraries to include. ' 'Can be specified multiple times.', default=[]) parser.add_argument('--secondary-native-libs', action='append', help='GYP-list of native libraries for secondary ' 'android-abi. Can be specified multiple times.', default=[]) parser.add_argument('--android-abi', help='Android architecture to use for native libraries') parser.add_argument('--secondary-android-abi', help='The secondary Android architecture to use for' 'secondary native libraries') parser.add_argument( '--is-multi-abi', action='store_true', help='Will add a placeholder for the missing ABI if no native libs or ' 'placeholders are set for either the primary or secondary ABI. Can only ' 'be set if both --android-abi and --secondary-android-abi are set.') parser.add_argument( '--native-lib-placeholders', help='GYP-list of native library placeholders to add.') parser.add_argument( '--secondary-native-lib-placeholders', help='GYP-list of native library placeholders to add ' 'for the secondary ABI') parser.add_argument('--uncompress-shared-libraries', default='False', choices=['true', 'True', 'false', 'False'], help='Whether to uncompress native shared libraries. Argument must be ' 'a boolean value.') parser.add_argument( '--apksigner-jar', help='Path to the apksigner executable.') parser.add_argument('--zipalign-path', help='Path to the zipalign executable.') parser.add_argument('--key-path', help='Path to keystore for signing.') parser.add_argument('--key-passwd', help='Keystore password') parser.add_argument('--key-name', help='Keystore name') parser.add_argument( '--min-sdk-version', required=True, help='Value of APK\'s minSdkVersion') parser.add_argument( '--best-compression', action='store_true', help='Use zip -9 rather than zip -1') parser.add_argument( '--library-always-compress', action='append', help='The list of library files that we always compress.') parser.add_argument( '--library-renames', action='append', help='The list of library files that we prepend crazy. to their names.') parser.add_argument('--warnings-as-errors', action='store_true', help='Treat all warnings as errors.') diff_utils.AddCommandLineFlags(parser) options = parser.parse_args(args) options.assets = build_utils.ParseGnList(options.assets) options.uncompressed_assets = build_utils.ParseGnList( options.uncompressed_assets) options.native_lib_placeholders = build_utils.ParseGnList( options.native_lib_placeholders) options.secondary_native_lib_placeholders = build_utils.ParseGnList( options.secondary_native_lib_placeholders) options.java_resources = build_utils.ParseGnList(options.java_resources) options.native_libs = build_utils.ParseGnList(options.native_libs) options.secondary_native_libs = build_utils.ParseGnList( options.secondary_native_libs) options.library_always_compress = build_utils.ParseGnList( options.library_always_compress) options.library_renames = build_utils.ParseGnList(options.library_renames) # --apksigner-jar, --zipalign-path, --key-xxx arguments are # required when building an APK, but not a bundle module. if options.format == 'apk': required_args = [ 'apksigner_jar', 'zipalign_path', 'key_path', 'key_passwd', 'key_name' ] for required in required_args: if not vars(options)[required]: raise Exception('Argument --%s is required for APKs.' % ( required.replace('_', '-'))) options.uncompress_shared_libraries = \ options.uncompress_shared_libraries in [ 'true', 'True' ] if not options.android_abi and (options.native_libs or options.native_lib_placeholders): raise Exception('Must specify --android-abi with --native-libs') if not options.secondary_android_abi and (options.secondary_native_libs or options.secondary_native_lib_placeholders): raise Exception('Must specify --secondary-android-abi with' ' --secondary-native-libs') if options.is_multi_abi and not (options.android_abi and options.secondary_android_abi): raise Exception('Must specify --is-multi-abi with both --android-abi ' 'and --secondary-android-abi.') return options