| Index: build/android/preprocess_google_play_services.py
|
| diff --git a/build/android/preprocess_google_play_services.py b/build/android/preprocess_google_play_services.py
|
| new file mode 100755
|
| index 0000000000000000000000000000000000000000..85d239ad30200ef5a8aef5d4abe722b433e7f383
|
| --- /dev/null
|
| +++ b/build/android/preprocess_google_play_services.py
|
| @@ -0,0 +1,238 @@
|
| +#!/usr/bin/env python
|
| +#
|
| +# Copyright 2015 The Chromium Authors. All rights reserved.
|
| +# Use of this source code is governed by a BSD-style license that can be
|
| +# found in the LICENSE file.
|
| +
|
| +'''Prepares the Google Play services split client libraries before usage by
|
| +Chrome's build system.
|
| +
|
| +We need to preprocess Google Play services before using it in Chrome
|
| +builds for 2 main reasons:
|
| +
|
| +- Getting rid of unused resources: unsupported languages, unused
|
| +drawables, etc.
|
| +
|
| +- Merging the differents jars so that it can be proguarded more
|
| +easily. This is necessary since debug and test apks get very close
|
| +to the dex limit.
|
| +
|
| +The script is supposed to be used with the maven repository that can be obtained
|
| +by downloading the "extra-google-m2repository" from the Android SDK Manager. It
|
| +also supports importing from already extracted AAR files using the
|
| +--is-extracted-repo flag.
|
| +
|
| +The json config (see the -c argument) file should provide the following fields:
|
| +
|
| +- lib_version: String. Used when building from the maven repository. It should
|
| + be the package's version (e.g. "7.3.0")
|
| +
|
| +- clients: String array. List of clients to pick. For example, when building
|
| + from the maven repository, it's the artifactId (e.g. "play-services-base") of
|
| + each client.
|
| +
|
| +- client_filter: String array. Pattern of files to prune from the clients once
|
| + extracted. Metacharacters are allowed. (e.g. "res/drawable*")
|
| +
|
| +The output is a directory with the following structure:
|
| +
|
| + OUT_DIR
|
| + +-- google-play-services.jar
|
| + +-- res
|
| + | +-- CLIENT_1
|
| + | | +-- color
|
| + | | +-- values
|
| + | | +-- etc.
|
| + | +-- CLIENT_2
|
| + | +-- ...
|
| + +-- stub
|
| + +-- res/[.git-keep-directory]
|
| + +-- src/android/UnusedStub.java
|
| +
|
| +Requires the `jar` utility in the path.
|
| +
|
| +'''
|
| +
|
| +import argparse
|
| +import glob
|
| +import itertools
|
| +import json
|
| +import os
|
| +import shutil
|
| +import stat
|
| +import sys
|
| +
|
| +from pylib import cmd_helper
|
| +from pylib import constants
|
| +
|
| +sys.path.append(
|
| + os.path.join(constants.DIR_SOURCE_ROOT, 'build', 'android', 'gyp'))
|
| +from util import build_utils
|
| +
|
| +
|
| +M2_PKG_PATH = os.path.join('com', 'google', 'android', 'gms')
|
| +
|
| +
|
| +def main():
|
| + parser = argparse.ArgumentParser(description=("Prepares the Google Play "
|
| + "services split client libraries before usage by Chrome's build system"))
|
| + parser.add_argument('-r',
|
| + '--repository',
|
| + help='The Google Play services repository location',
|
| + required=True,
|
| + metavar='FILE')
|
| + parser.add_argument('-o',
|
| + '--out-dir',
|
| + help='The output directory',
|
| + required=True,
|
| + metavar='FILE')
|
| + parser.add_argument('-c',
|
| + '--config-file',
|
| + help='Config file path',
|
| + required=True,
|
| + metavar='FILE')
|
| + parser.add_argument('-g',
|
| + '--git-friendly',
|
| + action='store_true',
|
| + default=False,
|
| + help='Add a .gitkeep file to the empty directories')
|
| + parser.add_argument('-x',
|
| + '--is-extracted-repo',
|
| + action='store_true',
|
| + default=False,
|
| + help='The provided repository is not made of AAR files.')
|
| +
|
| + args = parser.parse_args()
|
| +
|
| + ProcessGooglePlayServices(args.repository,
|
| + args.out_dir,
|
| + args.config_file,
|
| + args.git_friendly,
|
| + args.is_extracted_repo)
|
| +
|
| +
|
| +def ProcessGooglePlayServices(repo, out_dir, config_path, git_friendly,
|
| + is_extracted_repo):
|
| + with open(config_path, 'r') as json_file:
|
| + config = json.load(json_file)
|
| +
|
| + with build_utils.TempDir() as tmp_root:
|
| + tmp_paths = _SetupTempDir(tmp_root)
|
| +
|
| + if is_extracted_repo:
|
| + _ImportFromExtractedRepo(config, tmp_paths, repo)
|
| + else:
|
| + _ImportFromAars(config, tmp_paths, repo)
|
| +
|
| + _GenerateCombinedJar(tmp_paths)
|
| + _ProcessResources(config, tmp_paths)
|
| + _BuildOutput(config, tmp_paths, out_dir, git_friendly)
|
| +
|
| +
|
| +def _SetupTempDir(tmp_root):
|
| + tmp_paths = {
|
| + 'root': tmp_root,
|
| + 'imported_clients': os.path.join(tmp_root, 'imported_clients'),
|
| + 'extracted_jars': os.path.join(tmp_root, 'jar'),
|
| + 'combined_jar': os.path.join(tmp_root, 'google-play-services.jar'),
|
| + }
|
| + os.mkdir(tmp_paths['imported_clients'])
|
| + os.mkdir(tmp_paths['extracted_jars'])
|
| +
|
| + return tmp_paths
|
| +
|
| +
|
| +def _SetupOutputDir(out_dir):
|
| + out_paths = {
|
| + 'root': out_dir,
|
| + 'res': os.path.join(out_dir, 'res'),
|
| + 'jar': os.path.join(out_dir, 'google-play-services.jar'),
|
| + 'stub': os.path.join(out_dir, 'stub'),
|
| + }
|
| +
|
| + shutil.rmtree(out_paths['jar'], ignore_errors=True)
|
| + shutil.rmtree(out_paths['res'], ignore_errors=True)
|
| + shutil.rmtree(out_paths['stub'], ignore_errors=True)
|
| +
|
| + return out_paths
|
| +
|
| +
|
| +def _MakeWritable(dir_path):
|
| + for root, dirs, files in os.walk(dir_path):
|
| + for path in itertools.chain(dirs, files):
|
| + st = os.stat(os.path.join(root, path))
|
| + os.chmod(os.path.join(root, path), st.st_mode | stat.S_IWUSR)
|
| +
|
| +
|
| +def _ImportFromAars(config, tmp_paths, repo):
|
| + for client in config['clients']:
|
| + aar_name = '%s-%s.aar' % (client, config['lib_version'])
|
| + aar_path = os.path.join(repo, M2_PKG_PATH, client,
|
| + config['lib_version'], aar_name)
|
| + aar_out_path = os.path.join(tmp_paths['imported_clients'], client)
|
| + build_utils.ExtractAll(aar_path, aar_out_path)
|
| +
|
| + client_jar_path = os.path.join(aar_out_path, 'classes.jar')
|
| + build_utils.ExtractAll(client_jar_path, tmp_paths['extracted_jars'],
|
| + no_clobber=False)
|
| +
|
| +
|
| +def _ImportFromExtractedRepo(config, tmp_paths, repo):
|
| + # Import the clients
|
| + try:
|
| + for client in config['clients']:
|
| + client_out_dir = os.path.join(tmp_paths['imported_clients'], client)
|
| + shutil.copytree(os.path.join(repo, client), client_out_dir)
|
| +
|
| + client_jar_path = os.path.join(client_out_dir, 'classes.jar')
|
| + build_utils.ExtractAll(client_jar_path, tmp_paths['extracted_jars'],
|
| + no_clobber=False)
|
| + finally:
|
| + _MakeWritable(tmp_paths['imported_clients'])
|
| +
|
| +
|
| +def _GenerateCombinedJar(tmp_paths):
|
| + out_file_name = tmp_paths['combined_jar']
|
| + working_dir = tmp_paths['extracted_jars']
|
| + cmd_helper.Call(['jar', '-cf', out_file_name, '-C', working_dir, '.'])
|
| +
|
| +
|
| +def _ProcessResources(config, tmp_paths):
|
| + # Prune unused resources
|
| + for res_filter in config['client_filter']:
|
| + glob_pattern = os.path.join(tmp_paths['imported_clients'], '*', res_filter)
|
| + for prune_target in glob.glob(glob_pattern):
|
| + shutil.rmtree(prune_target)
|
| +
|
| +
|
| +def _BuildOutput(config, tmp_paths, out_dir, git_friendly):
|
| + out_paths = _SetupOutputDir(out_dir)
|
| +
|
| + # Copy the resources to the output dir
|
| + for client in config['clients']:
|
| + res_in_tmp_dir = os.path.join(tmp_paths['imported_clients'], client, 'res')
|
| + if os.path.isdir(res_in_tmp_dir) and os.listdir(res_in_tmp_dir):
|
| + res_in_final_dir = os.path.join(out_paths['res'], client)
|
| + shutil.copytree(res_in_tmp_dir, res_in_final_dir)
|
| +
|
| + # Copy the jar
|
| + shutil.copyfile(tmp_paths['combined_jar'], out_paths['jar'])
|
| +
|
| + # Write the java dummy stub. Needed for gyp to create the resource jar
|
| + stub_location = os.path.join(out_paths['stub'], 'src', 'android')
|
| + os.makedirs(stub_location)
|
| + with open(os.path.join(stub_location, 'UnusedStub.java'), 'w') as stub:
|
| + stub.write('package android;'
|
| + 'public final class UnusedStub {'
|
| + ' private UnusedStub() {}'
|
| + '}')
|
| +
|
| + # Create the main res directory. Will be empty but is needed by gyp
|
| + stub_res_location = os.path.join(out_paths['stub'], 'res')
|
| + os.makedirs(stub_res_location)
|
| + if git_friendly:
|
| + build_utils.Touch(os.path.join(stub_res_location, '.git-keep-directory'))
|
| +
|
| +
|
| +if __name__ == '__main__':
|
| + sys.exit(main())
|
|
|