Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(51)

Side by Side Diff: build/android/play_services/preprocess.py

Issue 1469913002: Cleanup gms update/preprocess scripts, roll android_tools (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address comments Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « build/android/play_services/config.json ('k') | build/android/play_services/update.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # 2 #
3 # Copyright 2015 The Chromium Authors. All rights reserved. 3 # Copyright 2015 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be 4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file. 5 # found in the LICENSE file.
6 6
7 '''Prepares the Google Play services split client libraries before usage by 7 '''Prepares the Google Play services split client libraries before usage by
8 Chrome's build system. 8 Chrome's build system.
9 9
10 We need to preprocess Google Play services before using it in Chrome 10 We need to preprocess Google Play services before using it in Chrome
(...skipping 11 matching lines...) Expand all
22 Manager. It also supports importing from already extracted AAR files using the 22 Manager. It also supports importing from already extracted AAR files using the
23 --is-extracted-repo flag. The expected directory structure in that case would 23 --is-extracted-repo flag. The expected directory structure in that case would
24 look like: 24 look like:
25 25
26 REPOSITORY_DIR 26 REPOSITORY_DIR
27 +-- CLIENT_1 27 +-- CLIENT_1
28 | +-- <content of the first AAR file> 28 | +-- <content of the first AAR file>
29 +-- CLIENT_2 29 +-- CLIENT_2
30 +-- etc. 30 +-- etc.
31 31
32 The json config (see the -c argument) file should provide the following fields:
33
34 - lib_version: String. Used when building from the maven repository. It should
35 be the package's version (e.g. "7.3.0"). Unused with extracted repositories.
36
37 - clients: String array. List of clients to pick. For example, when building
38 from the maven repository, it's the artifactId (e.g. "play-services-base") of
39 each client. With an extracted repository, it's the name of the
40 subdirectories.
41
42 - locale_whitelist: String array. Locales that should be allowed in the final
43 resources. They are specified the same way they are appended to the `values`
44 directory in android resources (e.g. "us-GB", "it", "fil").
45
46 The output is a directory with the following structure: 32 The output is a directory with the following structure:
47 33
48 OUT_DIR 34 OUT_DIR
49 +-- google-play-services.jar 35 +-- google-play-services.jar
50 +-- res 36 +-- res
51 | +-- CLIENT_1 37 | +-- CLIENT_1
52 | | +-- color 38 | | +-- color
53 | | +-- values 39 | | +-- values
54 | | +-- etc. 40 | | +-- etc.
55 | +-- CLIENT_2 41 | +-- CLIENT_2
56 | +-- ... 42 | +-- ...
57 +-- stub 43 +-- stub
58 +-- res/[.git-keep-directory] 44 +-- res/[.git-keep-directory]
59 +-- src/android/UnusedStub.java 45 +-- src/android/UnusedStub.java
60 46
61 Requires the `jar` utility in the path. 47 Requires the `jar` utility in the path.
62 48
63 ''' 49 '''
64 50
65 import argparse 51 import argparse
66 import glob 52 import glob
67 import itertools 53 import itertools
68 import json
69 import os 54 import os
70 import re
71 import shutil 55 import shutil
72 import stat 56 import stat
73 import sys 57 import sys
58 import tempfile
59 import zipfile
74 60
75 from datetime import datetime 61 from datetime import datetime
62
63 sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir))
76 from devil.utils import cmd_helper 64 from devil.utils import cmd_helper
77 from pylib import constants 65 from play_services import utils
78 66 from pylib.utils import argparse_utils
79 sys.path.append(
80 os.path.join(constants.DIR_SOURCE_ROOT, 'build', 'android', 'gyp'))
81 from util import build_utils # pylint: disable=import-error
82 67
83 68
84 M2_PKG_PATH = os.path.join('com', 'google', 'android', 'gms') 69 M2_PKG_PATH = os.path.join('com', 'google', 'android', 'gms')
85 OUTPUT_FORMAT_VERSION = 1 70
86 VERSION_FILE_NAME = 'version_info.json'
87 VERSION_NUMBER_PATTERN = re.compile(
88 r'<integer name="google_play_services_version">(\d+)<\/integer>')
89 71
90 def main(): 72 def main():
91 parser = argparse.ArgumentParser(description=("Prepares the Google Play " 73 parser = argparse.ArgumentParser(description=(
92 "services split client libraries before usage by Chrome's build system. " 74 "Prepares the Google Play services split client libraries before usage "
93 "See the script's documentation for more a detailed help.")) 75 "by Chrome's build system. See the script's documentation for more a "
94 parser.add_argument('-r', 76 "detailed help."))
95 '--repository', 77 argparse_utils.CustomHelpAction.EnableFor(parser)
96 help='The Google Play services repository location', 78 required_args = parser.add_argument_group('required named arguments')
97 required=True, 79 required_args.add_argument('-r',
98 metavar='FILE') 80 '--repository',
99 parser.add_argument('-o', 81 help=('the Google Play services repository '
100 '--out-dir', 82 'location'),
101 help='The output directory', 83 required=True,
102 required=True, 84 metavar='FILE')
103 metavar='FILE') 85 required_args.add_argument('-o',
104 parser.add_argument('-c', 86 '--out-dir',
105 '--config-file', 87 help='the output directory',
106 help='Config file path', 88 required=True,
107 required=True, 89 metavar='FILE')
108 metavar='FILE') 90 required_args.add_argument('-c',
91 '--config-file',
92 help='the config file path',
93 required=True,
94 metavar='FILE')
109 parser.add_argument('-x', 95 parser.add_argument('-x',
110 '--is-extracted-repo', 96 '--is-extracted-repo',
111 action='store_true', 97 action='store_true',
112 default=False, 98 help='the provided repository is not made of AAR files')
113 help='The provided repository is not made of AAR files.') 99 parser.add_argument('--config-help',
100 action='custom_help',
101 custom_help_text=utils.ConfigParser.__doc__,
102 help='show the configuration file format help')
114 103
115 args = parser.parse_args() 104 args = parser.parse_args()
116 105
117 ProcessGooglePlayServices(args.repository, 106 return ProcessGooglePlayServices(args.repository,
118 args.out_dir, 107 args.out_dir,
119 args.config_file, 108 args.config_file,
120 args.is_extracted_repo) 109 args.is_extracted_repo)
121 110
122 111
123 def ProcessGooglePlayServices(repo, out_dir, config_path, is_extracted_repo): 112 def ProcessGooglePlayServices(repo, out_dir, config_path, is_extracted_repo):
124 with open(config_path, 'r') as json_file: 113 config = utils.ConfigParser(config_path)
125 config = json.load(json_file)
126 114
127 with build_utils.TempDir() as tmp_root: 115 tmp_root = tempfile.mkdtemp()
116 try:
128 tmp_paths = _SetupTempDir(tmp_root) 117 tmp_paths = _SetupTempDir(tmp_root)
129 118
130 if is_extracted_repo: 119 if is_extracted_repo:
131 _ImportFromExtractedRepo(config, tmp_paths, repo) 120 _ImportFromExtractedRepo(config, tmp_paths, repo)
132 else: 121 else:
133 _ImportFromAars(config, tmp_paths, repo) 122 _ImportFromAars(config, tmp_paths, repo)
134 123
135 _GenerateCombinedJar(tmp_paths) 124 _GenerateCombinedJar(tmp_paths)
136 _ProcessResources(config, tmp_paths) 125 _ProcessResources(config, tmp_paths)
126 _BuildOutput(config, tmp_paths, out_dir)
127 finally:
128 shutil.rmtree(tmp_root)
137 129
138 if is_extracted_repo: 130 return 0
139 printable_repo = repo
140 else:
141 printable_repo = 'm2repository - ' + config['lib_version']
142 _BuildOutput(config, tmp_paths, out_dir, printable_repo)
143 131
144 132
145 def _SetupTempDir(tmp_root): 133 def _SetupTempDir(tmp_root):
146 tmp_paths = { 134 tmp_paths = {
147 'root': tmp_root, 135 'root': tmp_root,
148 'imported_clients': os.path.join(tmp_root, 'imported_clients'), 136 'imported_clients': os.path.join(tmp_root, 'imported_clients'),
149 'extracted_jars': os.path.join(tmp_root, 'jar'), 137 'extracted_jars': os.path.join(tmp_root, 'jar'),
150 'combined_jar': os.path.join(tmp_root, 'google-play-services.jar'), 138 'combined_jar': os.path.join(tmp_root, 'google-play-services.jar'),
151 } 139 }
152 os.mkdir(tmp_paths['imported_clients']) 140 os.mkdir(tmp_paths['imported_clients'])
153 os.mkdir(tmp_paths['extracted_jars']) 141 os.mkdir(tmp_paths['extracted_jars'])
154 142
155 return tmp_paths 143 return tmp_paths
156 144
157 145
158 def _SetupOutputDir(out_dir): 146 def _SetupOutputDir(out_dir):
159 out_paths = { 147 out_paths = {
160 'root': out_dir, 148 'root': out_dir,
161 'res': os.path.join(out_dir, 'res'), 149 'res': os.path.join(out_dir, 'res'),
162 'jar': os.path.join(out_dir, 'google-play-services.jar'), 150 'jar': os.path.join(out_dir, 'google-play-services.jar'),
163 'stub': os.path.join(out_dir, 'stub'), 151 'stub': os.path.join(out_dir, 'stub'),
164 } 152 }
165 153
166 shutil.rmtree(out_paths['jar'], ignore_errors=True) 154 shutil.rmtree(out_paths['jar'], ignore_errors=True)
167 shutil.rmtree(out_paths['res'], ignore_errors=True) 155 shutil.rmtree(out_paths['res'], ignore_errors=True)
168 shutil.rmtree(out_paths['stub'], ignore_errors=True) 156 shutil.rmtree(out_paths['stub'], ignore_errors=True)
169 157
170 return out_paths 158 return out_paths
171 159
172 160
173 def _MakeWritable(dir_path): 161 def _MakeWritable(dir_path):
174 for root, dirs, files in os.walk(dir_path): 162 for root, dirs, files in os.walk(dir_path):
175 for path in itertools.chain(dirs, files): 163 for path in itertools.chain(dirs, files):
176 st = os.stat(os.path.join(root, path)) 164 st = os.stat(os.path.join(root, path))
177 os.chmod(os.path.join(root, path), st.st_mode | stat.S_IWUSR) 165 os.chmod(os.path.join(root, path), st.st_mode | stat.S_IWUSR)
178 166
179 167
180 def _ImportFromAars(config, tmp_paths, repo): 168 def _ImportFromAars(config, tmp_paths, repo):
181 for client in config['clients']: 169 for client in config.clients:
182 aar_name = '%s-%s.aar' % (client, config['lib_version']) 170 aar_name = '%s-%s.aar' % (client, config.sdk_version)
183 aar_path = os.path.join(repo, M2_PKG_PATH, client, 171 aar_path = os.path.join(repo, M2_PKG_PATH, client,
184 config['lib_version'], aar_name) 172 config.sdk_version, aar_name)
185 aar_out_path = os.path.join(tmp_paths['imported_clients'], client) 173 aar_out_path = os.path.join(tmp_paths['imported_clients'], client)
186 build_utils.ExtractAll(aar_path, aar_out_path) 174 _ExtractAll(aar_path, aar_out_path)
187 175
188 client_jar_path = os.path.join(aar_out_path, 'classes.jar') 176 client_jar_path = os.path.join(aar_out_path, 'classes.jar')
189 build_utils.ExtractAll(client_jar_path, tmp_paths['extracted_jars'], 177 _ExtractAll(client_jar_path, tmp_paths['extracted_jars'])
190 no_clobber=False)
191 178
192 179
193 def _ImportFromExtractedRepo(config, tmp_paths, repo): 180 def _ImportFromExtractedRepo(config, tmp_paths, repo):
194 # Import the clients 181 # Import the clients
195 try: 182 try:
196 for client in config['clients']: 183 for client in config.clients:
197 client_out_dir = os.path.join(tmp_paths['imported_clients'], client) 184 client_out_dir = os.path.join(tmp_paths['imported_clients'], client)
198 shutil.copytree(os.path.join(repo, client), client_out_dir) 185 shutil.copytree(os.path.join(repo, client), client_out_dir)
199 186
200 client_jar_path = os.path.join(client_out_dir, 'classes.jar') 187 client_jar_path = os.path.join(client_out_dir, 'classes.jar')
201 build_utils.ExtractAll(client_jar_path, tmp_paths['extracted_jars'], 188 _ExtractAll(client_jar_path, tmp_paths['extracted_jars'])
202 no_clobber=False)
203 finally: 189 finally:
204 _MakeWritable(tmp_paths['imported_clients']) 190 _MakeWritable(tmp_paths['imported_clients'])
205 191
206 192
207 def _GenerateCombinedJar(tmp_paths): 193 def _GenerateCombinedJar(tmp_paths):
208 out_file_name = tmp_paths['combined_jar'] 194 out_file_name = tmp_paths['combined_jar']
209 working_dir = tmp_paths['extracted_jars'] 195 working_dir = tmp_paths['extracted_jars']
210 cmd_helper.Call(['jar', '-cf', out_file_name, '-C', working_dir, '.']) 196 cmd_helper.Call(['jar', '-cf', out_file_name, '-C', working_dir, '.'])
211 197
212 198
213 def _ProcessResources(config, tmp_paths): 199 def _ProcessResources(config, tmp_paths):
214 LOCALIZED_VALUES_BASE_NAME = 'values-' 200 LOCALIZED_VALUES_BASE_NAME = 'values-'
215 locale_whitelist = set(config['locale_whitelist']) 201 locale_whitelist = set(config.locale_whitelist)
216 202
217 glob_pattern = os.path.join(tmp_paths['imported_clients'], '*', 'res', '*') 203 glob_pattern = os.path.join(tmp_paths['imported_clients'], '*', 'res', '*')
218 for res_dir in glob.glob(glob_pattern): 204 for res_dir in glob.glob(glob_pattern):
219 dir_name = os.path.basename(res_dir) 205 dir_name = os.path.basename(res_dir)
220 206
221 if dir_name.startswith('drawable'): 207 if dir_name.startswith('drawable'):
222 shutil.rmtree(res_dir) 208 shutil.rmtree(res_dir)
223 continue 209 continue
224 210
225 if dir_name.startswith(LOCALIZED_VALUES_BASE_NAME): 211 if dir_name.startswith(LOCALIZED_VALUES_BASE_NAME):
226 dir_locale = dir_name[len(LOCALIZED_VALUES_BASE_NAME):] 212 dir_locale = dir_name[len(LOCALIZED_VALUES_BASE_NAME):]
227 if dir_locale not in locale_whitelist: 213 if dir_locale not in locale_whitelist:
228 shutil.rmtree(res_dir) 214 shutil.rmtree(res_dir)
229 215
230 216
231 def _GetVersionNumber(config, tmp_paths): 217 def _BuildOutput(config, tmp_paths, out_dir):
232 version_file_path = os.path.join(tmp_paths['imported_clients'],
233 config['base_client'],
234 'res',
235 'values',
236 'version.xml')
237
238 with open(version_file_path, 'r') as version_file:
239 version_file_content = version_file.read()
240
241 match = VERSION_NUMBER_PATTERN.search(version_file_content)
242 if not match:
243 raise AttributeError('A value for google_play_services_version was not '
244 'found in ' + version_file_path)
245
246 return match.group(1)
247
248
249 def _BuildOutput(config, tmp_paths, out_dir, printable_repo):
250 generation_date = datetime.utcnow() 218 generation_date = datetime.utcnow()
251 play_services_full_version = _GetVersionNumber(config, tmp_paths) 219 version_xml_path = os.path.join(tmp_paths['imported_clients'],
252 220 config.version_xml_path)
253 # Create a version text file to allow quickly checking the version 221 play_services_full_version = utils.GetVersionNumberFromLibraryResources(
254 gen_info = { 222 version_xml_path)
255 '@Description@': 'Preprocessed Google Play services clients for chrome',
256 'Generator script': os.path.basename(__file__),
257 'Repository source': printable_repo,
258 'Library version': play_services_full_version,
259 'Directory format version': OUTPUT_FORMAT_VERSION,
260 'Generation Date (UTC)': str(generation_date)
261 }
262 tmp_version_file_path = os.path.join(tmp_paths['root'], VERSION_FILE_NAME)
263 with open(tmp_version_file_path, 'w') as version_file:
264 json.dump(gen_info, version_file, indent=2, sort_keys=True)
265 223
266 out_paths = _SetupOutputDir(out_dir) 224 out_paths = _SetupOutputDir(out_dir)
267 225
268 # Copy the resources to the output dir 226 # Copy the resources to the output dir
269 for client in config['clients']: 227 for client in config.clients:
270 res_in_tmp_dir = os.path.join(tmp_paths['imported_clients'], client, 'res') 228 res_in_tmp_dir = os.path.join(tmp_paths['imported_clients'], client, 'res')
271 if os.path.isdir(res_in_tmp_dir) and os.listdir(res_in_tmp_dir): 229 if os.path.isdir(res_in_tmp_dir) and os.listdir(res_in_tmp_dir):
272 res_in_final_dir = os.path.join(out_paths['res'], client) 230 res_in_final_dir = os.path.join(out_paths['res'], client)
273 shutil.copytree(res_in_tmp_dir, res_in_final_dir) 231 shutil.copytree(res_in_tmp_dir, res_in_final_dir)
274 232
275 # Copy the jar 233 # Copy the jar
276 shutil.copyfile(tmp_paths['combined_jar'], out_paths['jar']) 234 shutil.copyfile(tmp_paths['combined_jar'], out_paths['jar'])
277 235
278 # Write the java dummy stub. Needed for gyp to create the resource jar 236 # Write the java dummy stub. Needed for gyp to create the resource jar
279 stub_location = os.path.join(out_paths['stub'], 'src', 'android') 237 stub_location = os.path.join(out_paths['stub'], 'src', 'android')
280 os.makedirs(stub_location) 238 os.makedirs(stub_location)
281 with open(os.path.join(stub_location, 'UnusedStub.java'), 'w') as stub: 239 with open(os.path.join(stub_location, 'UnusedStub.java'), 'w') as stub:
282 stub.write('package android;' 240 stub.write('package android;'
283 'public final class UnusedStub {' 241 'public final class UnusedStub {'
284 ' private UnusedStub() {}' 242 ' private UnusedStub() {}'
285 '}') 243 '}')
286 244
287 # Create the main res directory. It is needed by gyp 245 # Create the main res directory. It is needed by gyp
288 stub_res_location = os.path.join(out_paths['stub'], 'res') 246 stub_res_location = os.path.join(out_paths['stub'], 'res')
289 os.makedirs(stub_res_location) 247 os.makedirs(stub_res_location)
290 with open(os.path.join(stub_res_location, '.res-stamp'), 'w') as stamp: 248 with open(os.path.join(stub_res_location, '.res-stamp'), 'w') as stamp:
291 content_str = 'google_play_services_version: %s\nutc_date: %s\n' 249 content_str = 'google_play_services_version: %s\nutc_date: %s\n'
292 stamp.write(content_str % (play_services_full_version, generation_date)) 250 stamp.write(content_str % (play_services_full_version, generation_date))
293 251
294 shutil.copyfile(tmp_version_file_path, 252 config.UpdateVersionNumber(play_services_full_version)
295 os.path.join(out_paths['root'], VERSION_FILE_NAME))
296 253
297 254
255 def _ExtractAll(zip_path, out_path):
256 with zipfile.ZipFile(zip_path, 'r') as zip_file:
257 zip_file.extractall(out_path)
258
298 if __name__ == '__main__': 259 if __name__ == '__main__':
299 sys.exit(main()) 260 sys.exit(main())
OLDNEW
« no previous file with comments | « build/android/play_services/config.json ('k') | build/android/play_services/update.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698