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

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

Powered by Google App Engine
This is Rietveld 408576698