Esempio n. 1
0
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
Esempio n. 2
0
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
Esempio n. 3
0
def _ParseAndFlattenGnLists(gn_lists):
    ret = []
    for arg in gn_lists:
        ret.extend(build_utils.ParseGnList(arg))
    return ret
Esempio n. 4
0
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
Esempio n. 5
0
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
Esempio n. 6
0
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
Esempio n. 7
0
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)
Esempio n. 8
0
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)
Esempio n. 9
0
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
Esempio n. 10
0
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
Esempio n. 11
0
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.')
Esempio n. 12
0
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)
Esempio n. 13
0
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)
Esempio n. 14
0
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
Esempio n. 15
0
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)
Esempio n. 17
0
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)
Esempio n. 18
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('--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
Esempio n. 19
0
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
Esempio n. 20
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('--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
Esempio n. 21
0
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
Esempio n. 22
0
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)
Esempio n. 23
0
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
Esempio n. 24
0
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)
Esempio n. 27
0
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
Esempio n. 28
0
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
Esempio n. 29
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
Esempio n. 30
0
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