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

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: Created 5 years, 1 month 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
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:
dgn 2015/11/23 15:26:45 The description of this is now available when runn
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
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
dgn 2015/11/23 15:26:45 Got rid of that, since it's supposed to be reserve
82 66
83 67
84 M2_PKG_PATH = os.path.join('com', 'google', 'android', 'gms') 68 M2_PKG_PATH = os.path.join('com', 'google', 'android', 'gms')
85 OUTPUT_FORMAT_VERSION = 1 69 OUTPUT_FORMAT_VERSION = 1
86 VERSION_FILE_NAME = 'version_info.json' 70 VERSION_FILE_NAME = 'version_info.json'
87 VERSION_NUMBER_PATTERN = re.compile( 71
88 r'<integer name="google_play_services_version">(\d+)<\/integer>')
89 72
90 def main(): 73 def main():
91 parser = argparse.ArgumentParser(description=("Prepares the Google Play " 74 if '--config-help' in sys.argv:
92 "services split client libraries before usage by Chrome's build system. " 75 # We do this test before parsing the argument to be able to still show the
93 "See the script's documentation for more a detailed help.")) 76 # help when mandatory arguments are missing
77 print utils.ConfigParser.__doc__
78 return 0
79
80 parser = argparse.ArgumentParser(description=(
81 "Prepares the Google Play services split client libraries before usage "
82 "by Chrome's build system. See the script's documentation for more a "
83 "detailed help."))
94 parser.add_argument('-r', 84 parser.add_argument('-r',
95 '--repository', 85 '--repository',
96 help='The Google Play services repository location', 86 help='The Google Play services repository location',
97 required=True, 87 required=True,
98 metavar='FILE') 88 metavar='FILE')
99 parser.add_argument('-o', 89 parser.add_argument('-o',
100 '--out-dir', 90 '--out-dir',
101 help='The output directory', 91 help='The output directory',
102 required=True, 92 required=True,
103 metavar='FILE') 93 metavar='FILE')
104 parser.add_argument('-c', 94 parser.add_argument('-c',
105 '--config-file', 95 '--config-file',
106 help='Config file path', 96 help='Config file path',
107 required=True, 97 required=True,
108 metavar='FILE') 98 metavar='FILE')
109 parser.add_argument('-x', 99 parser.add_argument('-x',
110 '--is-extracted-repo', 100 '--is-extracted-repo',
111 action='store_true', 101 action='store_true',
112 default=False, 102 default=False,
113 help='The provided repository is not made of AAR files.') 103 help='The provided repository is not made of AAR files.')
104 parser.add_argument('--config-help',
105 action='store_true',
106 default=False,
107 help='Show the configuration file format help.')
114 108
115 args = parser.parse_args() 109 args = parser.parse_args()
116 110
117 ProcessGooglePlayServices(args.repository, 111 return ProcessGooglePlayServices(args.repository,
118 args.out_dir, 112 args.out_dir,
119 args.config_file, 113 args.config_file,
120 args.is_extracted_repo) 114 args.is_extracted_repo)
121 115
122 116
123 def ProcessGooglePlayServices(repo, out_dir, config_path, is_extracted_repo): 117 def ProcessGooglePlayServices(repo, out_dir, config_path, is_extracted_repo):
124 with open(config_path, 'r') as json_file: 118 config = utils.ConfigParser(config_path)
125 config = json.load(json_file)
126 119
127 with build_utils.TempDir() as tmp_root: 120 tmp_root = tempfile.mkdtemp()
121 try:
128 tmp_paths = _SetupTempDir(tmp_root) 122 tmp_paths = _SetupTempDir(tmp_root)
129 123
130 if is_extracted_repo: 124 if is_extracted_repo:
131 _ImportFromExtractedRepo(config, tmp_paths, repo) 125 _ImportFromExtractedRepo(config, tmp_paths, repo)
132 else: 126 else:
133 _ImportFromAars(config, tmp_paths, repo) 127 _ImportFromAars(config, tmp_paths, repo)
134 128
135 _GenerateCombinedJar(tmp_paths) 129 _GenerateCombinedJar(tmp_paths)
136 _ProcessResources(config, tmp_paths) 130 _ProcessResources(config, tmp_paths)
137 131
138 if is_extracted_repo: 132 if is_extracted_repo:
139 printable_repo = repo 133 printable_repo = repo
140 else: 134 else:
141 printable_repo = 'm2repository - ' + config['lib_version'] 135 printable_repo = 'm2repository - ' + config.sdk_version
142 _BuildOutput(config, tmp_paths, out_dir, printable_repo) 136 _BuildOutput(config, tmp_paths, out_dir, printable_repo)
137 finally:
138 shutil.rmtree(tmp_root)
139
140 return 0
143 141
144 142
145 def _SetupTempDir(tmp_root): 143 def _SetupTempDir(tmp_root):
146 tmp_paths = { 144 tmp_paths = {
147 'root': tmp_root, 145 'root': tmp_root,
148 'imported_clients': os.path.join(tmp_root, 'imported_clients'), 146 'imported_clients': os.path.join(tmp_root, 'imported_clients'),
149 'extracted_jars': os.path.join(tmp_root, 'jar'), 147 'extracted_jars': os.path.join(tmp_root, 'jar'),
150 'combined_jar': os.path.join(tmp_root, 'google-play-services.jar'), 148 'combined_jar': os.path.join(tmp_root, 'google-play-services.jar'),
151 } 149 }
152 os.mkdir(tmp_paths['imported_clients']) 150 os.mkdir(tmp_paths['imported_clients'])
153 os.mkdir(tmp_paths['extracted_jars']) 151 os.mkdir(tmp_paths['extracted_jars'])
154 152
155 return tmp_paths 153 return tmp_paths
156 154
157 155
158 def _SetupOutputDir(out_dir): 156 def _SetupOutputDir(out_dir):
159 out_paths = { 157 out_paths = {
160 'root': out_dir, 158 'root': out_dir,
161 'res': os.path.join(out_dir, 'res'), 159 'res': os.path.join(out_dir, 'res'),
162 'jar': os.path.join(out_dir, 'google-play-services.jar'), 160 'jar': os.path.join(out_dir, 'google-play-services.jar'),
163 'stub': os.path.join(out_dir, 'stub'), 161 'stub': os.path.join(out_dir, 'stub'),
164 } 162 }
165 163
166 shutil.rmtree(out_paths['jar'], ignore_errors=True) 164 shutil.rmtree(out_paths['jar'], ignore_errors=True)
167 shutil.rmtree(out_paths['res'], ignore_errors=True) 165 shutil.rmtree(out_paths['res'], ignore_errors=True)
168 shutil.rmtree(out_paths['stub'], ignore_errors=True) 166 shutil.rmtree(out_paths['stub'], ignore_errors=True)
169 167
170 return out_paths 168 return out_paths
171 169
172 170
173 def _MakeWritable(dir_path): 171 def _MakeWritable(dir_path):
174 for root, dirs, files in os.walk(dir_path): 172 for root, dirs, files in os.walk(dir_path):
175 for path in itertools.chain(dirs, files): 173 for path in itertools.chain(dirs, files):
176 st = os.stat(os.path.join(root, path)) 174 st = os.stat(os.path.join(root, path))
177 os.chmod(os.path.join(root, path), st.st_mode | stat.S_IWUSR) 175 os.chmod(os.path.join(root, path), st.st_mode | stat.S_IWUSR)
178 176
179 177
180 def _ImportFromAars(config, tmp_paths, repo): 178 def _ImportFromAars(config, tmp_paths, repo):
181 for client in config['clients']: 179 for client in config.clients:
182 aar_name = '%s-%s.aar' % (client, config['lib_version']) 180 aar_name = '%s-%s.aar' % (client, config.sdk_version)
183 aar_path = os.path.join(repo, M2_PKG_PATH, client, 181 aar_path = os.path.join(repo, M2_PKG_PATH, client,
184 config['lib_version'], aar_name) 182 config.sdk_version, aar_name)
185 aar_out_path = os.path.join(tmp_paths['imported_clients'], client) 183 aar_out_path = os.path.join(tmp_paths['imported_clients'], client)
186 build_utils.ExtractAll(aar_path, aar_out_path) 184 _ExtractAll(aar_path, aar_out_path)
187 185
188 client_jar_path = os.path.join(aar_out_path, 'classes.jar') 186 client_jar_path = os.path.join(aar_out_path, 'classes.jar')
189 build_utils.ExtractAll(client_jar_path, tmp_paths['extracted_jars'], 187 _ExtractAll(client_jar_path, tmp_paths['extracted_jars'])
190 no_clobber=False)
191 188
192 189
193 def _ImportFromExtractedRepo(config, tmp_paths, repo): 190 def _ImportFromExtractedRepo(config, tmp_paths, repo):
194 # Import the clients 191 # Import the clients
195 try: 192 try:
196 for client in config['clients']: 193 for client in config.clients:
197 client_out_dir = os.path.join(tmp_paths['imported_clients'], client) 194 client_out_dir = os.path.join(tmp_paths['imported_clients'], client)
198 shutil.copytree(os.path.join(repo, client), client_out_dir) 195 shutil.copytree(os.path.join(repo, client), client_out_dir)
199 196
200 client_jar_path = os.path.join(client_out_dir, 'classes.jar') 197 client_jar_path = os.path.join(client_out_dir, 'classes.jar')
201 build_utils.ExtractAll(client_jar_path, tmp_paths['extracted_jars'], 198 _ExtractAll(client_jar_path, tmp_paths['extracted_jars'])
202 no_clobber=False)
203 finally: 199 finally:
204 _MakeWritable(tmp_paths['imported_clients']) 200 _MakeWritable(tmp_paths['imported_clients'])
205 201
206 202
207 def _GenerateCombinedJar(tmp_paths): 203 def _GenerateCombinedJar(tmp_paths):
208 out_file_name = tmp_paths['combined_jar'] 204 out_file_name = tmp_paths['combined_jar']
209 working_dir = tmp_paths['extracted_jars'] 205 working_dir = tmp_paths['extracted_jars']
210 cmd_helper.Call(['jar', '-cf', out_file_name, '-C', working_dir, '.']) 206 cmd_helper.Call(['jar', '-cf', out_file_name, '-C', working_dir, '.'])
211 207
212 208
213 def _ProcessResources(config, tmp_paths): 209 def _ProcessResources(config, tmp_paths):
214 LOCALIZED_VALUES_BASE_NAME = 'values-' 210 LOCALIZED_VALUES_BASE_NAME = 'values-'
215 locale_whitelist = set(config['locale_whitelist']) 211 locale_whitelist = set(config.locale_whitelist)
216 212
217 glob_pattern = os.path.join(tmp_paths['imported_clients'], '*', 'res', '*') 213 glob_pattern = os.path.join(tmp_paths['imported_clients'], '*', 'res', '*')
218 for res_dir in glob.glob(glob_pattern): 214 for res_dir in glob.glob(glob_pattern):
219 dir_name = os.path.basename(res_dir) 215 dir_name = os.path.basename(res_dir)
220 216
221 if dir_name.startswith('drawable'): 217 if dir_name.startswith('drawable'):
222 shutil.rmtree(res_dir) 218 shutil.rmtree(res_dir)
223 continue 219 continue
224 220
225 if dir_name.startswith(LOCALIZED_VALUES_BASE_NAME): 221 if dir_name.startswith(LOCALIZED_VALUES_BASE_NAME):
226 dir_locale = dir_name[len(LOCALIZED_VALUES_BASE_NAME):] 222 dir_locale = dir_name[len(LOCALIZED_VALUES_BASE_NAME):]
227 if dir_locale not in locale_whitelist: 223 if dir_locale not in locale_whitelist:
228 shutil.rmtree(res_dir) 224 shutil.rmtree(res_dir)
229 225
230 226
231 def _GetVersionNumber(config, tmp_paths):
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): 227 def _BuildOutput(config, tmp_paths, out_dir, printable_repo):
250 generation_date = datetime.utcnow() 228 generation_date = datetime.utcnow()
251 play_services_full_version = _GetVersionNumber(config, tmp_paths) 229 version_xml_path = os.path.join(tmp_paths['imported_clients'],
230 config.version_xml_path)
231 play_services_full_version = utils.GetVersionNumberFromLibraryResources(
232 version_xml_path)
252 233
253 # Create a version text file to allow quickly checking the version 234 # Create a version text file to allow quickly checking the version
254 gen_info = { 235 gen_info = {
255 '@Description@': 'Preprocessed Google Play services clients for chrome', 236 '@Description@': 'Preprocessed Google Play services clients for chrome',
256 'Generator script': os.path.basename(__file__), 237 'Generator script': os.path.basename(__file__),
257 'Repository source': printable_repo, 238 'Repository source': printable_repo,
258 'Library version': play_services_full_version, 239 'Library version': play_services_full_version,
259 'Directory format version': OUTPUT_FORMAT_VERSION, 240 'Directory format version': OUTPUT_FORMAT_VERSION,
260 'Generation Date (UTC)': str(generation_date) 241 'Generation Date (UTC)': str(generation_date)
261 } 242 }
262 tmp_version_file_path = os.path.join(tmp_paths['root'], VERSION_FILE_NAME) 243 tmp_version_file_path = os.path.join(tmp_paths['root'], VERSION_FILE_NAME)
263 with open(tmp_version_file_path, 'w') as version_file: 244 with open(tmp_version_file_path, 'w') as version_file:
264 json.dump(gen_info, version_file, indent=2, sort_keys=True) 245 version_file.write(utils.DumpTrimmedJson(gen_info))
265 246
266 out_paths = _SetupOutputDir(out_dir) 247 out_paths = _SetupOutputDir(out_dir)
267 248
268 # Copy the resources to the output dir 249 # Copy the resources to the output dir
269 for client in config['clients']: 250 for client in config.clients:
270 res_in_tmp_dir = os.path.join(tmp_paths['imported_clients'], client, 'res') 251 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): 252 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) 253 res_in_final_dir = os.path.join(out_paths['res'], client)
273 shutil.copytree(res_in_tmp_dir, res_in_final_dir) 254 shutil.copytree(res_in_tmp_dir, res_in_final_dir)
274 255
275 # Copy the jar 256 # Copy the jar
276 shutil.copyfile(tmp_paths['combined_jar'], out_paths['jar']) 257 shutil.copyfile(tmp_paths['combined_jar'], out_paths['jar'])
277 258
278 # Write the java dummy stub. Needed for gyp to create the resource jar 259 # Write the java dummy stub. Needed for gyp to create the resource jar
279 stub_location = os.path.join(out_paths['stub'], 'src', 'android') 260 stub_location = os.path.join(out_paths['stub'], 'src', 'android')
280 os.makedirs(stub_location) 261 os.makedirs(stub_location)
281 with open(os.path.join(stub_location, 'UnusedStub.java'), 'w') as stub: 262 with open(os.path.join(stub_location, 'UnusedStub.java'), 'w') as stub:
282 stub.write('package android;' 263 stub.write('package android;'
283 'public final class UnusedStub {' 264 'public final class UnusedStub {'
284 ' private UnusedStub() {}' 265 ' private UnusedStub() {}'
285 '}') 266 '}')
286 267
287 # Create the main res directory. It is needed by gyp 268 # Create the main res directory. It is needed by gyp
288 stub_res_location = os.path.join(out_paths['stub'], 'res') 269 stub_res_location = os.path.join(out_paths['stub'], 'res')
289 os.makedirs(stub_res_location) 270 os.makedirs(stub_res_location)
290 with open(os.path.join(stub_res_location, '.res-stamp'), 'w') as stamp: 271 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' 272 content_str = 'google_play_services_version: %s\nutc_date: %s\n'
292 stamp.write(content_str % (play_services_full_version, generation_date)) 273 stamp.write(content_str % (play_services_full_version, generation_date))
293 274
294 shutil.copyfile(tmp_version_file_path, 275 shutil.copyfile(tmp_version_file_path,
295 os.path.join(out_paths['root'], VERSION_FILE_NAME)) 276 os.path.join(out_paths['root'], VERSION_FILE_NAME))
296 277
278 config.UpdateVersionNumber(play_services_full_version)
279
280
281 def _ExtractAll(zip_path, out_path):
282 with zipfile.ZipFile(zip_path, "r") as zip_file:
283 zip_file.extractall(out_path)
297 284
298 if __name__ == '__main__': 285 if __name__ == '__main__':
299 sys.exit(main()) 286 sys.exit(main())
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698