Пример #1
0
def main(args):
    args = build_utils.ExpandFileArgs(args)
    options = _ParseArgs(args)

    debug_temp_resources_dir = os.environ.get(_ENV_DEBUG_VARIABLE)
    if debug_temp_resources_dir:
        debug_temp_resources_dir = os.path.join(
            debug_temp_resources_dir, os.path.basename(options.arsc_path))
        build_utils.DeleteDirectory(debug_temp_resources_dir)
        build_utils.MakeDirectory(debug_temp_resources_dir)

    with resource_utils.BuildContext(debug_temp_resources_dir) as build:
        _PackageApk(options, build)

        # If --shared-resources-whitelist is used, the all resources listed in
        # the corresponding R.txt file will be non-final, and an onResourcesLoaded()
        # will be generated to adjust them at runtime.
        #
        # Otherwise, if --shared-resources is used, the all resources will be
        # non-final, and an onResourcesLoaded() method will be generated too.
        #
        # Otherwise, all resources will be final, and no method will be generated.
        #
        rjava_build_options = resource_utils.RJavaBuildOptions()
        if options.shared_resources_whitelist:
            rjava_build_options.ExportSomeResources(
                options.shared_resources_whitelist)
            rjava_build_options.GenerateOnResourcesLoaded()
        elif options.shared_resources or options.app_as_shared_lib:
            rjava_build_options.ExportAllResources()
            rjava_build_options.GenerateOnResourcesLoaded()

        custom_root_package_name = options.r_java_root_package_name
        grandparent_custom_package_name = None

        if options.package_name and not options.arsc_package_name:
            # Feature modules have their own custom root package name and should
            # inherit from the appropriate base module package. This behaviour should
            # not be present for test apks with an apk under test. Thus,
            # arsc_package_name is used as it is only defined for test apks with an
            # apk under test.
            custom_root_package_name = options.package_name
            grandparent_custom_package_name = options.r_java_root_package_name

        resource_utils.CreateRJavaFiles(
            build.srcjar_dir, None, build.r_txt_path,
            options.extra_res_packages, options.extra_r_text_files,
            rjava_build_options, options.srcjar_out, custom_root_package_name,
            grandparent_custom_package_name, options.extra_main_r_text_files)

        build_utils.ZipDir(build.srcjar_path, build.srcjar_dir)

        # Sanity check that the created resources have the expected package ID.
        if options.package_id:
            expected_id = options.package_id
        elif options.shared_resources:
            expected_id = 0
        else:
            expected_id = 127  # == '0x7f'.
        _, package_id = resource_utils.ExtractArscPackage(
            options.aapt2_path,
            build.arsc_path if options.arsc_path else build.proto_path)
        if package_id != expected_id:
            raise Exception('Invalid package ID 0x%x (expected 0x%x)' %
                            (package_id, expected_id))

        _WriteOutputs(options, build)

    if options.depfile:
        build_utils.WriteDepfile(options.depfile,
                                 options.srcjar_out,
                                 inputs=options.dependencies_res_zips +
                                 options.extra_r_text_files,
                                 add_pydeps=False)
Пример #2
0
def _OnStaleMd5(options):
  aapt = options.aapt_path
  with build_utils.TempDir() as temp_dir:
    deps_dir = os.path.join(temp_dir, 'deps')
    build_utils.MakeDirectory(deps_dir)
    v14_dir = os.path.join(temp_dir, 'v14')
    build_utils.MakeDirectory(v14_dir)

    gen_dir = os.path.join(temp_dir, 'gen')
    build_utils.MakeDirectory(gen_dir)
    r_txt_path = os.path.join(gen_dir, 'R.txt')
    srcjar_dir = os.path.join(temp_dir, 'java')

    input_resource_dirs = options.resource_dirs

    if not options.v14_skip:
      for resource_dir in input_resource_dirs:
        generate_v14_compatible_resources.GenerateV14Resources(
            resource_dir,
            v14_dir)

    dep_zips = options.dependencies_res_zips
    dep_subdirs = []
    for z in dep_zips:
      subdir = os.path.join(deps_dir, os.path.basename(z))
      if os.path.exists(subdir):
        raise Exception('Resource zip name conflict: ' + os.path.basename(z))
      build_utils.ExtractAll(z, path=subdir)
      dep_subdirs.append(subdir)

    # Generate R.java. This R.java contains non-final constants and is used only
    # while compiling the library jar (e.g. chromium_content.jar). When building
    # an apk, a new R.java file with the correct resource -> ID mappings will be
    # generated by merging the resources from all libraries and the main apk
    # project.
    package_command = [aapt,
                       'package',
                       '-m',
                       '-M', options.android_manifest,
                       '--auto-add-overlay',
                       '--no-version-vectors',
                       '-I', options.android_sdk_jar,
                       '--output-text-symbols', gen_dir,
                       '-J', gen_dir,  # Required for R.txt generation.
                       '--ignore-assets', build_utils.AAPT_IGNORE_PATTERN]

    # aapt supports only the "--include-all-resources" mode, where each R.java
    # file ends up with all symbols, rather than only those that it had at the
    # time it was originally generated. This subtle difference makes no
    # difference when compiling, but can lead to increased unused symbols in the
    # resulting R.class files.
    # TODO(agrieve): See if proguard makes this difference actually translate
    # into a size difference. If not, we can delete all of our custom R.java
    # template code above (and make include_all_resources the default).
    if options.include_all_resources:
      srcjar_dir = gen_dir
      if options.extra_res_packages:
        colon_separated = ':'.join(options.extra_res_packages)
        package_command += ['--extra-packages', colon_separated]
      if options.non_constant_id:
        package_command.append('--non-constant-id')
      if options.custom_package:
        package_command += ['--custom-package', options.custom_package]
      if options.shared_resources:
        package_command.append('--shared-lib')
      if options.app_as_shared_lib:
        package_command.append('--app-as-shared-lib')

    for d in input_resource_dirs:
      package_command += ['-S', d]

    # Adding all dependencies as sources is necessary for @type/foo references
    # to symbols within dependencies to resolve. However, it has the side-effect
    # that all Java symbols from dependencies are copied into the new R.java.
    # E.g.: It enables an arguably incorrect usage of
    # "mypackage.R.id.lib_symbol" where "libpackage.R.id.lib_symbol" would be
    # more correct. This is just how Android works.
    for d in dep_subdirs:
      package_command += ['-S', d]

    if options.proguard_file:
      package_command += ['-G', options.proguard_file]
    build_utils.CheckOutput(package_command, print_stderr=False)

    # When an empty res/ directory is passed, aapt does not write an R.txt.
    if not os.path.exists(r_txt_path):
      build_utils.Touch(r_txt_path)

    if not options.include_all_resources:
      packages = list(options.extra_res_packages)
      r_txt_files = list(options.extra_r_text_files)

      cur_package = options.custom_package
      if not options.custom_package:
        cur_package = _ExtractPackageFromManifest(options.android_manifest)

      # Don't create a .java file for the current resource target when:
      # - no package name was provided (either by manifest or build rules),
      # - there was already a dependent android_resources() with the same
      #   package (occurs mostly when an apk target and resources target share
      #   an AndroidManifest.xml)
      if cur_package != 'dummy.package' and cur_package not in packages:
        packages.append(cur_package)
        r_txt_files.append(r_txt_path)

      if packages:
        shared_resources = options.shared_resources or options.app_as_shared_lib
        CreateRJavaFiles(srcjar_dir, r_txt_path, packages, r_txt_files,
                         shared_resources)

    # This is the list of directories with resources to put in the final .zip
    # file. The order of these is important so that crunched/v14 resources
    # override the normal ones.
    zip_resource_dirs = input_resource_dirs + [v14_dir]

    base_crunch_dir = os.path.join(temp_dir, 'crunch')

    # Crunch image resources. This shrinks png files and is necessary for
    # 9-patch images to display correctly. 'aapt crunch' accepts only a single
    # directory at a time and deletes everything in the output directory.
    for idx, input_dir in enumerate(input_resource_dirs):
      crunch_dir = os.path.join(base_crunch_dir, str(idx))
      build_utils.MakeDirectory(crunch_dir)
      zip_resource_dirs.append(crunch_dir)
      CrunchDirectory(aapt, input_dir, crunch_dir)

    ZipResources(zip_resource_dirs, options.resource_zip_out)

    if options.all_resources_zip_out:
      CombineZips([options.resource_zip_out] + dep_zips,
                  options.all_resources_zip_out)

    if options.R_dir:
      build_utils.DeleteDirectory(options.R_dir)
      shutil.copytree(srcjar_dir, options.R_dir)
    else:
      build_utils.ZipDir(options.srcjar_out, srcjar_dir)

    if options.r_text_out:
      shutil.copyfile(r_txt_path, options.r_text_out)
Пример #3
0
def _OnStaleMd5(options):
  path = options.arsc_path or options.proto_path
  debug_temp_resources_dir = os.environ.get('TEMP_RESOURCES_DIR')
  if debug_temp_resources_dir:
    path = os.path.join(debug_temp_resources_dir, os.path.basename(path))
  else:
    # Use a deterministic temp directory since .pb files embed the absolute
    # path of resources: crbug.com/939984
    path = path + '.tmpdir'
  build_utils.DeleteDirectory(path)

  with resource_utils.BuildContext(
      temp_dir=path, keep_files=bool(debug_temp_resources_dir)) as build:

    manifest_package_name = _PackageApk(options, build)

    # If --shared-resources-allowlist is used, all the resources listed in the
    # corresponding R.txt file will be non-final, and an onResourcesLoaded()
    # will be generated to adjust them at runtime.
    #
    # Otherwise, if --shared-resources is used, the all resources will be
    # non-final, and an onResourcesLoaded() method will be generated too.
    #
    # Otherwise, all resources will be final, and no method will be generated.
    #
    rjava_build_options = resource_utils.RJavaBuildOptions()
    if options.shared_resources_allowlist:
      rjava_build_options.ExportSomeResources(
          options.shared_resources_allowlist)
      rjava_build_options.GenerateOnResourcesLoaded()
      if options.shared_resources:
        # The final resources will only be used in WebLayer, so hardcode the
        # package ID to be what WebLayer expects.
        rjava_build_options.SetFinalPackageId(
            protoresources.SHARED_LIBRARY_HARDCODED_ID)
    elif options.shared_resources or options.app_as_shared_lib:
      rjava_build_options.ExportAllResources()
      rjava_build_options.GenerateOnResourcesLoaded()

    custom_root_package_name = options.r_java_root_package_name
    grandparent_custom_package_name = None

    # Always generate an R.java file for the package listed in
    # AndroidManifest.xml because this is where Android framework looks to find
    # onResourcesLoaded() for shared library apks. While not actually necessary
    # for application apks, it also doesn't hurt.
    apk_package_name = manifest_package_name

    if options.package_name and not options.arsc_package_name:
      # Feature modules have their own custom root package name and should
      # inherit from the appropriate base module package. This behaviour should
      # not be present for test apks with an apk under test. Thus,
      # arsc_package_name is used as it is only defined for test apks with an
      # apk under test.
      custom_root_package_name = options.package_name
      grandparent_custom_package_name = options.r_java_root_package_name
      # Feature modules have the same manifest package as the base module but
      # they should not create an R.java for said manifest package because it
      # will be created in the base module.
      apk_package_name = None

    logging.debug('Creating R.srcjar')
    resource_utils.CreateRJavaFiles(
        build.srcjar_dir, apk_package_name, build.r_txt_path,
        options.extra_res_packages, rjava_build_options, options.srcjar_out,
        custom_root_package_name, grandparent_custom_package_name,
        options.extra_main_r_text_files)
    build_utils.ZipDir(build.srcjar_path, build.srcjar_dir)

    # Sanity check that the created resources have the expected package ID.
    logging.debug('Performing sanity check')
    if options.package_id:
      expected_id = options.package_id
    elif options.shared_resources:
      expected_id = 0
    else:
      expected_id = 127  # == '0x7f'.
    _, package_id = resource_utils.ExtractArscPackage(
        options.aapt2_path,
        build.arsc_path if options.arsc_path else build.proto_path)
    if package_id != expected_id:
      raise Exception(
          'Invalid package ID 0x%x (expected 0x%x)' % (package_id, expected_id))

    logging.debug('Copying outputs')
    _WriteOutputs(options, build)
Пример #4
0
def buildWebApp(buildtype, version, destination, zip_path, manifest_template,
                appid, app_client_id, app_name, app_description,
                app_capabilities, manifest_key, files, files_listfile,
                locales_listfile, jinja_paths, service_environment, use_gcd):
    """Does the main work of building the webapp directory and zipfile.

  Args:
    buildtype: the type of build ("Official", "Release" or "Dev").
    destination: A string with path to directory where the webapp will be
                 written.
    zipfile: A string with path to the zipfile to create containing the
             contents of |destination|.
    manifest_template: jinja2 template file for manifest.
    appid: A string with the Remoting Application Id (only used for app
           remoting webapps). If supplied, it defaults to using the
           test API server.
    app_client_id: The OAuth2 client ID for the webapp.
    app_name: A string with the name of the application.
    app_description: A string with the description of the application.
    app_capabilities: A set of strings naming the capabilities that should be
                      enabled for this application.
    manifest_key: The manifest key for the webapp.
    files: An array of strings listing the paths for resources to include
           in this webapp.
    files_listfile: The name of a file containing a list of files, one per
                    line, identifying the resources to include in this webapp.
                    This is an alternate to specifying the files directly via
                    the 'files' option. The files listed in this file are
                    appended to the files passed via the 'files' option, if any.
    locales_listfile: The name of a file containing a list of locales, one per
                      line, which are copied, along with their directory
                      structure, from the _locales directory down.
    jinja_paths: An array of paths to search for {%include} directives in
                 addition to the directory containing the manifest template.
    service_environment: Used to point the webapp to the dev/prod environments.
    use_gcd: True if GCD support should be enabled.
  """

    # Load the locales files from the locales_listfile.
    if not locales_listfile:
        raise Exception('You must specify a locales_listfile')
    locales = []
    with open(locales_listfile) as input:
        for s in input:
            locales.append(s.rstrip())

    # Load the files from the files_listfile.
    if files_listfile:
        with open(files_listfile) as input:
            for s in input:
                files.append(s.rstrip())


#Ensure a fresh directory.
    try:
        shutil.rmtree(destination)
    except OSError:
        if os.path.exists(destination):
            raise
        else:
            pass
    os.makedirs(destination, 0775)

    if buildtype != 'Official' and buildtype != 'Release' and buildtype != 'Dev':
        raise Exception('Unknown buildtype: ' + buildtype)

    jinja_context = {
        'buildtype': buildtype,
    }

    # Copy all the files.
    for current_file in files:
        destination_file = os.path.join(destination,
                                        os.path.basename(current_file))

        # Process *.jinja2 files as jinja2 templates
        if current_file.endswith(".jinja2"):
            destination_file = destination_file[:-len(".jinja2")]
            processJinjaTemplate(current_file, jinja_paths, destination_file,
                                 jinja_context)
        else:
            shutil.copy2(current_file, destination_file)

    # Copy all the locales, preserving directory structure
    destination_locales = os.path.join(destination, '_locales')
    os.mkdir(destination_locales, 0775)
    remoting_locales = os.path.join(destination, 'remoting_locales')
    os.mkdir(remoting_locales, 0775)
    for current_locale in locales:
        extension = os.path.splitext(current_locale)[1]
        if extension == '.json':
            locale_id = os.path.split(os.path.split(current_locale)[0])[1]
            destination_dir = os.path.join(destination_locales, locale_id)
            destination_file = os.path.join(destination_dir,
                                            os.path.split(current_locale)[1])
            os.mkdir(destination_dir, 0775)
            shutil.copy2(current_locale, destination_file)
        elif extension == '.pak':
            destination_file = os.path.join(remoting_locales,
                                            os.path.split(current_locale)[1])
            shutil.copy2(current_locale, destination_file)
        else:
            raise Exception('Unknown extension: ' + current_locale)

    is_prod_service_environment = service_environment == 'prod'

    # Allow host names for google services/apis to be overriden via env vars.
    oauth2AccountsHost = os.environ.get('OAUTH2_ACCOUNTS_HOST',
                                        'https://accounts.google.com')
    oauth2ApiHost = os.environ.get('OAUTH2_API_HOST',
                                   'https://www.googleapis.com')
    directoryApiHost = os.environ.get('DIRECTORY_API_HOST',
                                      'https://www.googleapis.com')
    remotingApiHost = os.environ.get('REMOTING_API_HOST',
                                     'https://remoting-pa.googleapis.com')

    oauth2BaseUrl = oauth2AccountsHost + '/o/oauth2'
    oauth2ApiBaseUrl = oauth2ApiHost + '/oauth2'
    directoryApiBaseUrl = directoryApiHost + '/chromoting/v1'
    telemetryApiBaseUrl = remotingApiHost + '/v1/events'

    replaceBool(destination, 'USE_GCD', use_gcd)
    replaceString(destination, 'OAUTH2_BASE_URL', oauth2BaseUrl)
    replaceString(destination, 'OAUTH2_API_BASE_URL', oauth2ApiBaseUrl)
    replaceString(destination, 'DIRECTORY_API_BASE_URL', directoryApiBaseUrl)
    replaceString(destination, 'TELEMETRY_API_BASE_URL', telemetryApiBaseUrl)

    # Substitute hosts in the manifest's CSP list.
    # Ensure we list the API host only once if it's the same for multiple APIs.
    googleApiHosts = ' '.join(set([oauth2ApiHost, directoryApiHost]))

    # WCS and the OAuth trampoline are both hosted on talkgadget. Split them into
    # separate suffix/prefix variables to allow for wildcards in manifest.json.
    talkGadgetHostSuffix = os.environ.get('TALK_GADGET_HOST_SUFFIX',
                                          'talkgadget.google.com')
    talkGadgetHostPrefix = os.environ.get('TALK_GADGET_HOST_PREFIX',
                                          'https://chromoting-client.')
    oauth2RedirectHostPrefix = os.environ.get('OAUTH2_REDIRECT_HOST_PREFIX',
                                              'https://chromoting-oauth.')

    # Use a wildcard in the manifest.json host specs if the prefixes differ.
    talkGadgetHostJs = talkGadgetHostPrefix + talkGadgetHostSuffix
    talkGadgetBaseUrl = talkGadgetHostJs + '/talkgadget'
    if talkGadgetHostPrefix == oauth2RedirectHostPrefix:
        talkGadgetHostJson = talkGadgetHostJs
    else:
        talkGadgetHostJson = 'https://*.' + talkGadgetHostSuffix

    # Set the correct OAuth2 redirect URL.
    oauth2RedirectHostJs = oauth2RedirectHostPrefix + talkGadgetHostSuffix
    oauth2RedirectHostJson = talkGadgetHostJson
    oauth2RedirectPath = '/talkgadget/oauth/chrome-remote-desktop'
    oauth2RedirectBaseUrlJs = oauth2RedirectHostJs + oauth2RedirectPath
    oauth2RedirectBaseUrlJson = oauth2RedirectHostJson + oauth2RedirectPath
    if buildtype == 'Official':
        oauth2RedirectUrlJs = (
            "'" + oauth2RedirectBaseUrlJs +
            "/rel/' + chrome.i18n.getMessage('@@extension_id')")
        oauth2RedirectUrlJson = oauth2RedirectBaseUrlJson + '/rel/*'
    else:
        oauth2RedirectUrlJs = "'" + oauth2RedirectBaseUrlJs + "/dev'"
        oauth2RedirectUrlJson = oauth2RedirectBaseUrlJson + '/dev*'
    thirdPartyAuthUrlJs = oauth2RedirectBaseUrlJs + '/thirdpartyauth'
    thirdPartyAuthUrlJson = oauth2RedirectBaseUrlJson + '/thirdpartyauth*'
    xmppServer = os.environ.get('XMPP_SERVER', 'talk.google.com:443')

    replaceString(destination, 'TALK_GADGET_URL', talkGadgetBaseUrl)
    findAndReplace(os.path.join(destination, 'plugin_settings.js'),
                   "'OAUTH2_REDIRECT_URL'", oauth2RedirectUrlJs)

    # Configure xmpp server and directory bot settings in the plugin.
    xmpp_server_user_tls = getenvBool('XMPP_SERVER_USE_TLS', True)
    if (buildtype != 'Dev' and not xmpp_server_user_tls):
        raise Exception('TLS can must be enabled in non Dev builds.')

    replaceBool(destination, 'XMPP_SERVER_USE_TLS', xmpp_server_user_tls)
    replaceString(destination, 'XMPP_SERVER', xmppServer)
    replaceString(
        destination, 'DIRECTORY_BOT_JID',
        os.environ.get('DIRECTORY_BOT_JID', '*****@*****.**'))
    replaceString(destination, 'THIRD_PARTY_AUTH_REDIRECT_URL',
                  thirdPartyAuthUrlJs)

    # Set the correct API keys.
    # For overriding the client ID/secret via env vars, see google_api_keys.py.
    apiClientId = google_api_keys.GetClientID('REMOTING')
    apiClientSecret = google_api_keys.GetClientSecret('REMOTING')

    apiClientIdV2 = os.environ.get(
        'REMOTING_IDENTITY_API_CLIENT_ID',
        google_api_keys.GetClientID('REMOTING_IDENTITY_API'))

    replaceString(destination, 'API_CLIENT_ID', apiClientId)
    replaceString(destination, 'API_CLIENT_SECRET', apiClientSecret)

    # Use a fixed key in the app manifest. For dev builds, this ensures that the
    # app can be run directly from the output directory. For official CRD builds,
    # it allows QA to test the app without uploading it to Chrome Web Store.
    manifest_key = 'remotingdevbuild'

    # Generate manifest.
    if manifest_template:
        context = {
            'FULL_APP_VERSION': version,
            'MANIFEST_KEY': manifest_key,
            'OAUTH2_REDIRECT_URL': oauth2RedirectUrlJson,
            'TALK_GADGET_HOST': talkGadgetHostJson,
            'THIRD_PARTY_AUTH_REDIRECT_URL': thirdPartyAuthUrlJson,
            'REMOTING_IDENTITY_API_CLIENT_ID': apiClientIdV2,
            'OAUTH2_BASE_URL': oauth2BaseUrl,
            'OAUTH2_API_BASE_URL': oauth2ApiBaseUrl,
            'DIRECTORY_API_BASE_URL': directoryApiBaseUrl,
            'TELEMETRY_API_BASE_URL': telemetryApiBaseUrl,
            'CLOUD_PRINT_URL': '',
            'OAUTH2_ACCOUNTS_HOST': oauth2AccountsHost,
            'GOOGLE_API_HOSTS': googleApiHosts,
            'APP_NAME': app_name,
            'APP_DESCRIPTION': app_description,
            'OAUTH_CLOUD_PRINT_SCOPE': '',
            'OAUTH_GDRIVE_SCOPE': '',
            'USE_GCD': use_gcd,
            'XMPP_SERVER': xmppServer,
            # An URL match pattern that is added to the |permissions| section of the
            # manifest in case some URLs are redirected by corporate proxies.
            'PROXY_URL': os.environ.get('PROXY_URL', ''),
        }
        if 'CLOUD_PRINT' in app_capabilities:
            context['OAUTH_CLOUD_PRINT_SCOPE'] = (
                '"https://www.googleapis.com/auth/cloudprint",')
            context['CLOUD_PRINT_URL'] = (
                '"https://www.google.com/cloudprint/*",')
        if 'GOOGLE_DRIVE' in app_capabilities:
            context['OAUTH_GDRIVE_SCOPE'] = (
                '"https://docs.google.com/feeds/", '
                '"https://www.googleapis.com/auth/drive",')
        processJinjaTemplate(manifest_template, jinja_paths,
                             os.path.join(destination, 'manifest.json'),
                             context)

    # Make the zipfile.
    build_utils.ZipDir(zip_path,
                       destination,
                       compress_fn=lambda _: zipfile.ZIP_DEFLATED,
                       zip_prefix_path=os.path.splitext(
                           os.path.basename(zip_path))[0])

    return 0
Пример #5
0
def main():
    args = build_utils.ExpandFileArgs(sys.argv[1:])

    options = ParseArgs(args)
    android_jar = os.path.join(options.android_sdk, 'android.jar')
    aapt = os.path.join(options.android_sdk_tools, 'aapt')

    input_files = []

    with build_utils.TempDir() as temp_dir:
        deps_dir = os.path.join(temp_dir, 'deps')
        build_utils.MakeDirectory(deps_dir)
        v14_dir = os.path.join(temp_dir, 'v14')
        build_utils.MakeDirectory(v14_dir)

        gen_dir = os.path.join(temp_dir, 'gen')
        build_utils.MakeDirectory(gen_dir)

        input_resource_dirs = build_utils.ParseGypList(options.resource_dirs)

        if not options.v14_skip:
            for resource_dir in input_resource_dirs:
                generate_v14_compatible_resources.GenerateV14Resources(
                    resource_dir, v14_dir)

        dep_zips = build_utils.ParseGypList(options.dependencies_res_zips)
        input_files += dep_zips
        dep_subdirs = []
        for z in dep_zips:
            subdir = os.path.join(deps_dir, os.path.basename(z))
            if os.path.exists(subdir):
                raise Exception('Resource zip name conflict: ' +
                                os.path.basename(z))
            build_utils.ExtractAll(z, path=subdir)
            dep_subdirs.append(subdir)

        # Generate R.java. This R.java contains non-final constants and is used only
        # while compiling the library jar (e.g. chromium_content.jar). When building
        # an apk, a new R.java file with the correct resource -> ID mappings will be
        # generated by merging the resources from all libraries and the main apk
        # project.
        package_command = [
            aapt, 'package', '-m', '-M', options.android_manifest,
            '--auto-add-overlay', '-I', android_jar, '--output-text-symbols',
            gen_dir, '-J', gen_dir, '--ignore-assets',
            build_utils.AAPT_IGNORE_PATTERN
        ]

        for d in input_resource_dirs:
            package_command += ['-S', d]

        for d in dep_subdirs:
            package_command += ['-S', d]

        if options.non_constant_id:
            package_command.append('--non-constant-id')
        if options.custom_package:
            package_command += ['--custom-package', options.custom_package]
        if options.proguard_file:
            package_command += ['-G', options.proguard_file]
        if options.shared_resources:
            package_command.append('--shared-lib')
        build_utils.CheckOutput(package_command, print_stderr=False)

        if options.extra_res_packages:
            CreateExtraRJavaFiles(
                gen_dir, build_utils.ParseGypList(options.extra_res_packages),
                build_utils.ParseGypList(options.extra_r_text_files),
                options.shared_resources, options.include_all_resources)

        # This is the list of directories with resources to put in the final .zip
        # file. The order of these is important so that crunched/v14 resources
        # override the normal ones.
        zip_resource_dirs = input_resource_dirs + [v14_dir]

        base_crunch_dir = os.path.join(temp_dir, 'crunch')

        # Crunch image resources. This shrinks png files and is necessary for
        # 9-patch images to display correctly. 'aapt crunch' accepts only a single
        # directory at a time and deletes everything in the output directory.
        for idx, input_dir in enumerate(input_resource_dirs):
            crunch_dir = os.path.join(base_crunch_dir, str(idx))
            build_utils.MakeDirectory(crunch_dir)
            zip_resource_dirs.append(crunch_dir)
            CrunchDirectory(aapt, input_dir, crunch_dir)

        ZipResources(zip_resource_dirs, options.resource_zip_out)

        if options.all_resources_zip_out:
            CombineZips([options.resource_zip_out] + dep_zips,
                        options.all_resources_zip_out)

        if options.R_dir:
            build_utils.DeleteDirectory(options.R_dir)
            shutil.copytree(gen_dir, options.R_dir)
        else:
            build_utils.ZipDir(options.srcjar_out, gen_dir)

        if options.r_text_out:
            r_text_path = os.path.join(gen_dir, 'R.txt')
            if os.path.exists(r_text_path):
                shutil.copyfile(r_text_path, options.r_text_out)
            else:
                open(options.r_text_out, 'w').close()

    if options.depfile:
        input_files += build_utils.GetPythonDependencies()
        build_utils.WriteDepfile(options.depfile, input_files)

    if options.stamp:
        build_utils.Touch(options.stamp)
Пример #6
0
def main(argv):
    parser = optparse.OptionParser()
    build_utils.AddDepfileOption(parser)
    parser.add_option("--protoc", help="Path to protoc binary.")
    parser.add_option("--proto-path", help="Path to proto directory.")
    parser.add_option("--java-out-dir",
                      help="Path to output directory for java files.")
    parser.add_option("--srcjar", help="Path to output srcjar.")
    parser.add_option("--stamp", help="File to touch on success.")
    parser.add_option("--nano",
                      help="Use to generate nano protos.",
                      action='store_true')
    parser.add_option(
        "--import-dir",
        action="append",
        default=[],
        help="Extra import directory for protos, can be repeated.")
    options, args = parser.parse_args(argv)

    build_utils.CheckOptions(options, parser, ['protoc', 'proto_path'])
    if not options.java_out_dir and not options.srcjar:
        print('One of --java-out-dir or --srcjar must be specified.')
        return 1

    proto_path_args = ['--proto_path', options.proto_path]
    for path in options.import_dir:
        proto_path_args += ["--proto_path", path]

    with build_utils.TempDir() as temp_dir:
        if options.nano:
            # Specify arguments to the generator.
            generator_args = [
                'optional_field_style=reftypes', 'store_unknown_fields=true'
            ]
            out_arg = '--javanano_out=' + ','.join(
                generator_args) + ':' + temp_dir
        else:
            out_arg = '--java_out=lite:' + temp_dir

        # Generate Java files using protoc.
        build_utils.CheckOutput(
            [options.protoc] + proto_path_args + [out_arg] + args,
            # protoc generates superfluous warnings about LITE_RUNTIME deprecation
            # even though we are using the new non-deprecated method.
            stderr_filter=lambda output: build_utils.FilterLines(
                output, '|'.join(
                    [r'optimize_for = LITE_RUNTIME', r'java/lite\.md'])))

        if options.java_out_dir:
            build_utils.DeleteDirectory(options.java_out_dir)
            shutil.copytree(temp_dir, options.java_out_dir)
        else:
            build_utils.ZipDir(options.srcjar, temp_dir)

    if options.depfile:
        assert options.srcjar
        deps = args + [options.protoc]
        build_utils.WriteDepfile(options.depfile,
                                 options.srcjar,
                                 deps,
                                 add_pydeps=False)

    if options.stamp:
        build_utils.Touch(options.stamp)
Пример #7
0
def main(argv):
    parser = optparse.OptionParser()
    build_utils.AddDepfileOption(parser)
    parser.add_option("--protoc", help="Path to protoc binary.")
    parser.add_option("--proto-path", help="Path to proto directory.")
    parser.add_option("--java-out-dir",
                      help="Path to output directory for java files.")
    parser.add_option("--srcjar", help="Path to output srcjar.")
    parser.add_option("--stamp", help="File to touch on success.")
    parser.add_option("--nano",
                      help="Use to generate nano protos.",
                      action='store_true')
    options, args = parser.parse_args(argv)

    build_utils.CheckOptions(options, parser, ['protoc', 'proto_path'])
    if not options.java_out_dir and not options.srcjar:
        print 'One of --java-out-dir or --srcjar must be specified.'
        return 1

    with build_utils.TempDir() as temp_dir:
        if options.nano:
            # Specify arguments to the generator.
            generator_args = [
                'optional_field_style=reftypes', 'store_unknown_fields=true'
            ]
            out_arg = '--javanano_out=' + ','.join(
                generator_args) + ':' + temp_dir
        else:
            out_arg = '--java_out=' + temp_dir

            # Check if all proto files (which are listed in the args) are opting to
            # use the lite runtime, otherwise we'd have to include the much heavier
            # regular proto runtime in Chrome.
            # TODO(jkrcal): Replace this check by '--java_lite_out=' for the out_arg
            # above once this works on the master branch of the protobuf library,
            # expected in version 4.0 (see https://crbug.com/800281).
            for proto_file in args:
                if not 'LITE_RUNTIME' in open(proto_file).read():
                    raise Exception(
                        'Chrome only supports lite protos. Please add "optimize_for = '
                        'LITE_RUNTIME" to your proto file to enable the lite runtime.'
                    )
        # Generate Java files using protoc.
        build_utils.CheckOutput(
            [options.protoc, '--proto_path', options.proto_path, out_arg] +
            args)

        if options.java_out_dir:
            build_utils.DeleteDirectory(options.java_out_dir)
            shutil.copytree(temp_dir, options.java_out_dir)
        else:
            build_utils.ZipDir(options.srcjar, temp_dir)

    if options.depfile:
        assert options.srcjar
        deps = args + [options.protoc]
        build_utils.WriteDepfile(options.depfile,
                                 options.srcjar,
                                 deps,
                                 add_pydeps=False)

    if options.stamp:
        build_utils.Touch(options.stamp)
Пример #8
0
def _OnStaleMd5(options):
    path = options.arsc_path or options.proto_path
    debug_temp_resources_dir = os.environ.get('TEMP_RESOURCES_DIR')
    if debug_temp_resources_dir:
        path = os.path.join(debug_temp_resources_dir, os.path.basename(path))
    else:
        # Use a deterministic temp directory since .pb files embed the absolute
        # path of resources: crbug.com/939984
        path = path + '.tmpdir'
    build_utils.DeleteDirectory(path)

    with resource_utils.BuildContext(
            temp_dir=path, keep_files=bool(debug_temp_resources_dir)) as build:
        manifest_package_name = _PackageApk(options, build)

        # If --shared-resources-allowlist is used, the all resources listed in
        # the corresponding R.txt file will be non-final, and an onResourcesLoaded()
        # will be generated to adjust them at runtime.
        #
        # Otherwise, if --shared-resources is used, the all resources will be
        # non-final, and an onResourcesLoaded() method will be generated too.
        #
        # Otherwise, all resources will be final, and no method will be generated.
        #
        rjava_build_options = resource_utils.RJavaBuildOptions()
        if options.shared_resources_allowlist:
            rjava_build_options.ExportSomeResources(
                options.shared_resources_allowlist)
            rjava_build_options.GenerateOnResourcesLoaded()
        elif options.shared_resources or options.app_as_shared_lib:
            rjava_build_options.ExportAllResources()
            rjava_build_options.GenerateOnResourcesLoaded()

        custom_root_package_name = options.r_java_root_package_name
        grandparent_custom_package_name = None

        if options.package_name and not options.arsc_package_name:
            # Feature modules have their own custom root package name and should
            # inherit from the appropriate base module package. This behaviour should
            # not be present for test apks with an apk under test. Thus,
            # arsc_package_name is used as it is only defined for test apks with an
            # apk under test.
            custom_root_package_name = options.package_name
            grandparent_custom_package_name = options.r_java_root_package_name

        if options.shared_resources or options.app_as_shared_lib:
            package_for_library = manifest_package_name
        else:
            package_for_library = None

        logging.debug('Creating R.srcjar')
        resource_utils.CreateRJavaFiles(
            build.srcjar_dir, package_for_library, build.r_txt_path,
            options.extra_res_packages, options.extra_r_text_files,
            rjava_build_options, options.srcjar_out, custom_root_package_name,
            grandparent_custom_package_name, options.extra_main_r_text_files)
        build_utils.ZipDir(build.srcjar_path, build.srcjar_dir)

        # Sanity check that the created resources have the expected package ID.
        logging.debug('Performing sanity check')
        if options.package_id:
            expected_id = options.package_id
        elif options.shared_resources:
            expected_id = 0
        else:
            expected_id = 127  # == '0x7f'.
        _, package_id = resource_utils.ExtractArscPackage(
            options.aapt2_path,
            build.arsc_path if options.arsc_path else build.proto_path)
        if package_id != expected_id:
            raise Exception('Invalid package ID 0x%x (expected 0x%x)' %
                            (package_id, expected_id))

        logging.debug('Copying outputs')
        _WriteOutputs(options, build)
Пример #9
0
def main(args):
    options, paths = _ParseArgs(args)
    if ((options.proguard_enabled == 'true'
         and options.configuration_name == 'Release')
            or (options.debug_build_proguard_enabled == 'true'
                and options.configuration_name == 'Debug')):
        paths = [options.proguard_enabled_input_path]

    if options.inputs:
        paths += options.inputs

    if options.excluded_paths:
        # Excluded paths are relative to the output directory.
        exclude_paths = options.excluded_paths
        paths = [
            p for p in paths if
            not os.path.relpath(p, options.output_directory) in exclude_paths
        ]

    input_paths = list(paths)
    if options.multi_dex:
        input_paths.append(options.main_dex_list_path)

    dex_cmd = ['java', '-jar', options.d8_jar_path, '--no-desugaring']
    if options.multi_dex:
        dex_cmd += ['--main-dex-list', options.main_dex_list_path]
    if options.release:
        dex_cmd += ['--release']
    if options.min_api:
        dex_cmd += ['--min-api', options.min_api]

    is_dex = options.dex_path.endswith('.dex')
    is_jar = options.dex_path.endswith('.jar')

    if is_jar and _NoClassFiles(paths):
        # Handle case where no classfiles are specified in inputs
        # by creating an empty JAR
        with zipfile.ZipFile(options.dex_path, 'w') as outfile:
            outfile.comment = 'empty'
    else:
        # .dex files can't specify a name for D8. Instead, we output them to a
        # temp directory then move them after the command has finished running
        # (see _MoveTempDexFile). For other files, tmp_dex_dir is None.
        with build_utils.TempDir() as tmp_dex_dir:
            _RunD8(dex_cmd, paths, tmp_dex_dir)
            if is_dex:
                _MoveTempDexFile(tmp_dex_dir, options.dex_path)
            else:
                # d8 supports outputting to a .zip, but does not have deterministic file
                # ordering: https://issuetracker.google.com/issues/119945929
                build_utils.ZipDir(options.dex_path, tmp_dex_dir)

    if options.dexlayout_profile:
        with build_utils.TempDir() as temp_dir:
            binary_profile = _CreateBinaryProfile(options.dexlayout_profile,
                                                  options.dex_path,
                                                  options.profman_path,
                                                  temp_dir)
            output_files = _LayoutDex(binary_profile, options.dex_path,
                                      options.dexlayout_path, temp_dir)
            target = None
            if len(output_files) > 1:
                target = _ZipMultidex(temp_dir, output_files)
            else:
                target = output_files[0]
            shutil.move(os.path.join(temp_dir, target), options.dex_path)

    build_utils.WriteDepfile(options.depfile,
                             options.dex_path,
                             input_paths,
                             add_pydeps=False)
Пример #10
0
def main(args):
    build_utils.InitLogging('RESOURCE_DEBUG')
    args = build_utils.ExpandFileArgs(args)
    options = _ParseArgs(args)

    if options.expected_file:
        actual_data = _CreateNormalizedManifestForVerification(options)
        diff_utils.CheckExpectations(actual_data, options)
        if options.only_verify_expectations:
            return

    path = options.arsc_path or options.proto_path
    debug_temp_resources_dir = os.environ.get('TEMP_RESOURCES_DIR')
    if debug_temp_resources_dir:
        path = os.path.join(debug_temp_resources_dir, os.path.basename(path))
    else:
        # Use a deterministic temp directory since .pb files embed the absolute
        # path of resources: crbug.com/939984
        path = path + '.tmpdir'
    build_utils.DeleteDirectory(path)

    with resource_utils.BuildContext(
            temp_dir=path, keep_files=bool(debug_temp_resources_dir)) as build:

        manifest_package_name = _PackageApk(options, build)

        # If --shared-resources-allowlist is used, all the resources listed in the
        # corresponding R.txt file will be non-final, and an onResourcesLoaded()
        # will be generated to adjust them at runtime.
        #
        # Otherwise, if --shared-resources is used, the all resources will be
        # non-final, and an onResourcesLoaded() method will be generated too.
        #
        # Otherwise, all resources will be final, and no method will be generated.
        #
        rjava_build_options = resource_utils.RJavaBuildOptions()
        if options.shared_resources_allowlist:
            rjava_build_options.ExportSomeResources(
                options.shared_resources_allowlist)
            rjava_build_options.GenerateOnResourcesLoaded()
            if options.shared_resources:
                # The final resources will only be used in WebLayer, so hardcode the
                # package ID to be what WebLayer expects.
                rjava_build_options.SetFinalPackageId(
                    protoresources.SHARED_LIBRARY_HARDCODED_ID)
        elif options.shared_resources or options.app_as_shared_lib:
            rjava_build_options.ExportAllResources()
            rjava_build_options.GenerateOnResourcesLoaded()

        custom_root_package_name = options.r_java_root_package_name
        grandparent_custom_package_name = None

        # Always generate an R.java file for the package listed in
        # AndroidManifest.xml because this is where Android framework looks to find
        # onResourcesLoaded() for shared library apks. While not actually necessary
        # for application apks, it also doesn't hurt.
        apk_package_name = manifest_package_name

        if options.package_name and not options.arsc_package_name:
            # Feature modules have their own custom root package name and should
            # inherit from the appropriate base module package. This behaviour should
            # not be present for test apks with an apk under test. Thus,
            # arsc_package_name is used as it is only defined for test apks with an
            # apk under test.
            custom_root_package_name = options.package_name
            grandparent_custom_package_name = options.r_java_root_package_name
            # Feature modules have the same manifest package as the base module but
            # they should not create an R.java for said manifest package because it
            # will be created in the base module.
            apk_package_name = None

        logging.debug('Creating R.srcjar')
        resource_utils.CreateRJavaFiles(
            build.srcjar_dir, apk_package_name, build.r_txt_path,
            options.extra_res_packages, rjava_build_options,
            options.srcjar_out, custom_root_package_name,
            grandparent_custom_package_name, options.extra_main_r_text_files)
        build_utils.ZipDir(build.srcjar_path, build.srcjar_dir)

        logging.debug('Copying outputs')
        _WriteOutputs(options, build)

    if options.depfile:
        depfile_deps = (options.dependencies_res_zips +
                        options.dependencies_res_zip_overlays +
                        options.extra_main_r_text_files +
                        options.include_resources)
        build_utils.WriteDepfile(options.depfile, options.srcjar_out,
                                 depfile_deps)
Пример #11
0
def main(args):
    args = build_utils.ExpandFileArgs(args)
    options = _ParseArgs(args)

    debug_temp_resources_dir = os.environ.get(_ENV_DEBUG_VARIABLE)
    if debug_temp_resources_dir:
        debug_temp_resources_dir = os.path.join(
            debug_temp_resources_dir, os.path.basename(options.arsc_path))
        build_utils.DeleteDirectory(debug_temp_resources_dir)
        build_utils.MakeDirectory(debug_temp_resources_dir)

    with resource_utils.BuildContext(debug_temp_resources_dir) as build:
        _PackageApk(options, build)

        # If --shared-resources-whitelist is used, the all resources listed in
        # the corresponding R.txt file will be non-final, and an onResourcesLoaded()
        # will be generated to adjust them at runtime.
        #
        # Otherwise, if --shared-resources is used, the all resources will be
        # non-final, and an onResourcesLoaded() method will be generated too.
        #
        # Otherwise, all resources will be final, and no method will be generated.
        #
        rjava_build_options = resource_utils.RJavaBuildOptions()
        if options.shared_resources_whitelist:
            rjava_build_options.ExportSomeResources(
                options.shared_resources_whitelist)
            rjava_build_options.GenerateOnResourcesLoaded()
        elif options.shared_resources or options.app_as_shared_lib:
            rjava_build_options.ExportAllResources()
            rjava_build_options.GenerateOnResourcesLoaded()

        resource_utils.CreateRJavaFiles(build.srcjar_dir, None,
                                        build.r_txt_path,
                                        options.extra_res_packages,
                                        options.extra_r_text_files,
                                        rjava_build_options,
                                        options.srcjar_out)

        build_utils.ZipDir(build.srcjar_path, build.srcjar_dir)

        # Sanity check that the created resources have the expected package ID.
        expected_id = _PackageIdFromOptions(options)
        if expected_id is None:
            expected_id = '0x00' if options.shared_resources else '0x7f'
        expected_id = int(expected_id, 16)
        _, package_id = resource_utils.ExtractArscPackage(
            options.aapt2_path,
            build.arsc_path if options.arsc_path else build.proto_path)
        if package_id != expected_id:
            raise Exception('Invalid package ID 0x%x (expected 0x%x)' %
                            (package_id, expected_id))

        _WriteOutputs(options, build)

    if options.depfile:
        build_utils.WriteDepfile(options.depfile,
                                 options.srcjar_out,
                                 inputs=options.dependencies_res_zips +
                                 options.extra_r_text_files,
                                 add_pydeps=False)