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

Side by Side Diff: build/mac/tweak_info_plist.py

Issue 2037043002: [iOS] Add support for iOS to build/mac/tweak_info_plist.py. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Move mapping from "ios/mac" to "iOS/Mac" to Main() Created 4 years, 6 months 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 | « no previous file | no next file » | 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 (c) 2012 The Chromium Authors. All rights reserved. 3 # Copyright (c) 2012 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 # 7 #
8 # Xcode supports build variable substitutions and CPP; sadly, that doesn't work 8 # Xcode supports build variable substitutions and CPP; sadly, that doesn't work
9 # because: 9 # because:
10 # 10 #
(...skipping 13 matching lines...) Expand all
24 import os 24 import os
25 import plistlib 25 import plistlib
26 import re 26 import re
27 import subprocess 27 import subprocess
28 import sys 28 import sys
29 import tempfile 29 import tempfile
30 30
31 TOP = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) 31 TOP = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
32 32
33 33
34 def _ConvertPlist(source_plist, output_plist, fmt):
35 """Convert |source_plist| to |fmt| and save as |output_plist|."""
36 return subprocess.call(
37 ['plutil', '-convert', fmt, '-o', output_plist, source_plist])
38
39
34 def _GetOutput(args): 40 def _GetOutput(args):
35 """Runs a subprocess and waits for termination. Returns (stdout, returncode) 41 """Runs a subprocess and waits for termination. Returns (stdout, returncode)
36 of the process. stderr is attached to the parent.""" 42 of the process. stderr is attached to the parent."""
37 proc = subprocess.Popen(args, stdout=subprocess.PIPE) 43 proc = subprocess.Popen(args, stdout=subprocess.PIPE)
38 (stdout, stderr) = proc.communicate() 44 (stdout, stderr) = proc.communicate()
39 return (stdout, proc.returncode) 45 return (stdout, proc.returncode)
40 46
41 47
42 def _GetOutputNoError(args): 48 def _GetOutputNoError(args):
43 """Similar to _GetOutput() but ignores stderr. If there's an error launching 49 """Similar to _GetOutput() but ignores stderr. If there's an error launching
(...skipping 10 matching lines...) Expand all
54 60
55 def _RemoveKeys(plist, *keys): 61 def _RemoveKeys(plist, *keys):
56 """Removes a varargs of keys from the plist.""" 62 """Removes a varargs of keys from the plist."""
57 for key in keys: 63 for key in keys:
58 try: 64 try:
59 del plist[key] 65 del plist[key]
60 except KeyError: 66 except KeyError:
61 pass 67 pass
62 68
63 69
64 def _AddVersionKeys(plist, version=None): 70 def _ApplyVersionOverrides(version, keys, overrides, separator='.'):
71 """Applies version overrides.
72
73 Given a |version| string as "a.b.c.d" (assuming a default separator) with
74 version components named by |keys| then overrides any value that is present
75 in |overrides|.
76
77 >>> _ApplyVersionOverrides('a.b', ['major', 'minor'], {'minor': 'd'})
78 'a.d'
79 """
80 if not overrides:
81 return version
82 version_values = version.split(separator)
83 for i, (key, value) in enumerate(zip(keys, version_values)):
84 if key in overrides:
85 version_values[i] = overrides[key]
86 return separator.join(version_values)
87
88
89 def _AddVersionKeys(plist, version=None, overrides=None):
65 """Adds the product version number into the plist. Returns True on success and 90 """Adds the product version number into the plist. Returns True on success and
66 False on error. The error will be printed to stderr.""" 91 False on error. The error will be printed to stderr."""
67 if version: 92 if version:
68 match = re.match('\d+\.\d+\.(\d+\.\d+)$', version) 93 match = re.match('\d+\.\d+\.(\d+\.\d+)$', version)
69 if not match: 94 if not match:
70 print >>sys.stderr, 'Invalid version string specified: "%s"' % version 95 print >>sys.stderr, 'Invalid version string specified: "%s"' % version
71 return False 96 return False
72 97
73 full_version = match.group(0) 98 full_version = match.group(0)
74 bundle_version = match.group(1) 99 bundle_version = match.group(1)
75 100
76 else: 101 else:
77 # Pull in the Chrome version number. 102 # Pull in the Chrome version number.
78 VERSION_TOOL = os.path.join(TOP, 'build/util/version.py') 103 VERSION_TOOL = os.path.join(TOP, 'build/util/version.py')
79 VERSION_FILE = os.path.join(TOP, 'chrome/VERSION') 104 VERSION_FILE = os.path.join(TOP, 'chrome/VERSION')
80 105
81 (stdout, retval1) = _GetOutput([VERSION_TOOL, '-f', VERSION_FILE, '-t', 106 (stdout, retval1) = _GetOutput([VERSION_TOOL, '-f', VERSION_FILE, '-t',
82 '@MAJOR@.@MINOR@.@BUILD@.@PATCH@']) 107 '@MAJOR@.@MINOR@.@BUILD@.@PATCH@'])
83 full_version = stdout.rstrip() 108 full_version = _ApplyVersionOverrides(
109 stdout.rstrip(), ('MAJOR', 'MINOR', 'BUILD', 'PATCH'), overrides)
84 110
85 (stdout, retval2) = _GetOutput([VERSION_TOOL, '-f', VERSION_FILE, '-t', 111 (stdout, retval2) = _GetOutput([VERSION_TOOL, '-f', VERSION_FILE, '-t',
86 '@BUILD@.@PATCH@']) 112 '@BUILD@.@PATCH@'])
87 bundle_version = stdout.rstrip() 113 bundle_version = _ApplyVersionOverrides(
114 stdout.rstrip(), ('BUILD', 'PATCH'), overrides)
88 115
89 # If either of the two version commands finished with non-zero returncode, 116 # If either of the two version commands finished with non-zero returncode,
90 # report the error up. 117 # report the error up.
91 if retval1 or retval2: 118 if retval1 or retval2:
92 return False 119 return False
93 120
94 # Add public version info so "Get Info" works. 121 # Add public version info so "Get Info" works.
95 plist['CFBundleShortVersionString'] = full_version 122 plist['CFBundleShortVersionString'] = full_version
96 123
97 # Honor the 429496.72.95 limit. The maximum comes from splitting 2^32 - 1 124 # Honor the 429496.72.95 limit. The maximum comes from splitting 2^32 - 1
(...skipping 26 matching lines...) Expand all
124 # See if the operation failed. 151 # See if the operation failed.
125 _RemoveKeys(plist, 'SCMRevision') 152 _RemoveKeys(plist, 'SCMRevision')
126 if scm_revision != None: 153 if scm_revision != None:
127 plist['SCMRevision'] = scm_revision 154 plist['SCMRevision'] = scm_revision
128 elif add_keys: 155 elif add_keys:
129 print >>sys.stderr, 'Could not determine SCM revision. This may be OK.' 156 print >>sys.stderr, 'Could not determine SCM revision. This may be OK.'
130 157
131 return True 158 return True
132 159
133 160
134 def _AddBreakpadKeys(plist, branding): 161 def _AddBreakpadKeys(plist, branding, platform):
135 """Adds the Breakpad keys. This must be called AFTER _AddVersionKeys() and 162 """Adds the Breakpad keys. This must be called AFTER _AddVersionKeys() and
136 also requires the |branding| argument.""" 163 also requires the |branding| argument."""
137 plist['BreakpadReportInterval'] = '3600' # Deliberately a string. 164 plist['BreakpadReportInterval'] = '3600' # Deliberately a string.
138 plist['BreakpadProduct'] = '%s_Mac' % branding 165 plist['BreakpadProduct'] = '%s_%s' % (branding, platform)
139 plist['BreakpadProductDisplay'] = branding 166 plist['BreakpadProductDisplay'] = branding
140 plist['BreakpadVersion'] = plist['CFBundleShortVersionString'] 167 plist['BreakpadVersion'] = plist['CFBundleShortVersionString']
141 # These are both deliberately strings and not boolean. 168 # These are both deliberately strings and not boolean.
142 plist['BreakpadSendAndExit'] = 'YES' 169 plist['BreakpadSendAndExit'] = 'YES'
143 plist['BreakpadSkipConfirm'] = 'YES' 170 plist['BreakpadSkipConfirm'] = 'YES'
144 171
145 172
146 def _RemoveBreakpadKeys(plist): 173 def _RemoveBreakpadKeys(plist):
147 """Removes any set Breakpad keys.""" 174 """Removes any set Breakpad keys."""
148 _RemoveKeys(plist, 175 _RemoveKeys(plist,
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 help='Enable Breakpad\'s uploading of crash dumps [1 or 0]') 240 help='Enable Breakpad\'s uploading of crash dumps [1 or 0]')
214 parser.add_option('--keystone', dest='use_keystone', action='store', 241 parser.add_option('--keystone', dest='use_keystone', action='store',
215 type='int', default=False, help='Enable Keystone [1 or 0]') 242 type='int', default=False, help='Enable Keystone [1 or 0]')
216 parser.add_option('--scm', dest='add_scm_info', action='store', type='int', 243 parser.add_option('--scm', dest='add_scm_info', action='store', type='int',
217 default=True, help='Add SCM metadata [1 or 0]') 244 default=True, help='Add SCM metadata [1 or 0]')
218 parser.add_option('--branding', dest='branding', action='store', 245 parser.add_option('--branding', dest='branding', action='store',
219 type='string', default=None, help='The branding of the binary') 246 type='string', default=None, help='The branding of the binary')
220 parser.add_option('--bundle_id', dest='bundle_identifier', 247 parser.add_option('--bundle_id', dest='bundle_identifier',
221 action='store', type='string', default=None, 248 action='store', type='string', default=None,
222 help='The bundle id of the binary') 249 help='The bundle id of the binary')
250 parser.add_option('--platform', choices=('ios', 'mac'), default='mac',
251 help='The target platform of the bundle')
252 parser.add_option('--version-overrides', action='append',
253 help='Key-value pair to override specific component of version '
254 'like key=value (can be passed multiple time to configure '
255 'more than one override)')
256 parser.add_option('--format', choices=('binary1', 'xml1', 'json'),
257 default='xml1', help='Format to use when writing property list '
258 '(default: %(default)s)')
223 parser.add_option('--version', dest='version', action='store', type='string', 259 parser.add_option('--version', dest='version', action='store', type='string',
224 default=None, help='The version string [major.minor.build.patch]') 260 default=None, help='The version string [major.minor.build.patch]')
225 (options, args) = parser.parse_args(argv) 261 (options, args) = parser.parse_args(argv)
226 262
227 if len(args) > 0: 263 if len(args) > 0:
228 print >>sys.stderr, parser.get_usage() 264 print >>sys.stderr, parser.get_usage()
229 return 1 265 return 1
230 266
231 if not options.plist_path: 267 if not options.plist_path:
232 print >>sys.stderr, 'No --plist specified.' 268 print >>sys.stderr, 'No --plist specified.'
233 return 1 269 return 1
234 270
235 # Read the plist into its parsed format. 271 # Read the plist into its parsed format. Convert the file to 'xml1' as
236 plist = plistlib.readPlist(options.plist_path) 272 # plistlib only supports that format in Python 2.7.
273 with tempfile.NamedTemporaryFile() as temp_info_plist:
274 retcode = _ConvertPlist(options.plist_path, temp_info_plist.name, 'xml1')
275 if retcode != 0:
276 return retcode
277 plist = plistlib.readPlist(temp_info_plist.name)
278
279 # Convert overrides.
280 overrides = {}
281 if options.version_overrides:
282 for pair in options.version_overrides:
283 if not '=' in pair:
284 print >>sys.stderr, 'Invalid value for --version-overrides:', pair
285 return 1
286 key, value = pair.split('=', 1)
287 overrides[key] = value
288 if key not in ('MAJOR', 'MINOR', 'BUILD', 'PATCH'):
289 print >>sys.stderr, 'Unsupported key for --version-overrides:', key
290 return 1
237 291
238 # Insert the product version. 292 # Insert the product version.
239 if not _AddVersionKeys(plist, version=options.version): 293 if not _AddVersionKeys(plist, version=options.version, overrides=overrides):
240 return 2 294 return 2
241 295
242 # Add Breakpad if configured to do so. 296 # Add Breakpad if configured to do so.
243 if options.use_breakpad: 297 if options.use_breakpad:
244 if options.branding is None: 298 if options.branding is None:
245 print >>sys.stderr, 'Use of Breakpad requires branding.' 299 print >>sys.stderr, 'Use of Breakpad requires branding.'
246 return 1 300 return 1
247 _AddBreakpadKeys(plist, options.branding) 301 # Map gyp "OS" / gn "target_os" passed via the --platform parameter to
302 # the platform as known by breakpad.
303 platform = {'mac': 'Mac', 'ios': 'iOS'}[options.platform]
304 _AddBreakpadKeys(plist, options.branding, platform)
248 if options.breakpad_uploads: 305 if options.breakpad_uploads:
249 plist['BreakpadURL'] = 'https://clients2.google.com/cr/report' 306 plist['BreakpadURL'] = 'https://clients2.google.com/cr/report'
250 else: 307 else:
251 # This allows crash dumping to a file without uploading the 308 # This allows crash dumping to a file without uploading the
252 # dump, for testing purposes. Breakpad does not recognise 309 # dump, for testing purposes. Breakpad does not recognise
253 # "none" as a special value, but this does stop crash dump 310 # "none" as a special value, but this does stop crash dump
254 # uploading from happening. We need to specify something 311 # uploading from happening. We need to specify something
255 # because if "BreakpadURL" is not present, Breakpad will not 312 # because if "BreakpadURL" is not present, Breakpad will not
256 # register its crash handler and no crash dumping will occur. 313 # register its crash handler and no crash dumping will occur.
257 plist['BreakpadURL'] = 'none' 314 plist['BreakpadURL'] = 'none'
258 else: 315 else:
259 _RemoveBreakpadKeys(plist) 316 _RemoveBreakpadKeys(plist)
260 317
261 # Add Keystone if configured to do so. 318 # Add Keystone if configured to do so.
262 if options.use_keystone: 319 if options.use_keystone:
263 if options.bundle_identifier is None: 320 if options.bundle_identifier is None:
264 print >>sys.stderr, 'Use of Keystone requires the bundle id.' 321 print >>sys.stderr, 'Use of Keystone requires the bundle id.'
265 return 1 322 return 1
266 _AddKeystoneKeys(plist, options.bundle_identifier) 323 _AddKeystoneKeys(plist, options.bundle_identifier)
267 else: 324 else:
268 _RemoveKeystoneKeys(plist) 325 _RemoveKeystoneKeys(plist)
269 326
270 # Adds or removes any SCM keys. 327 # Adds or removes any SCM keys.
271 if not _DoSCMKeys(plist, options.add_scm_info): 328 if not _DoSCMKeys(plist, options.add_scm_info):
272 return 3 329 return 3
273 330
274 # Now that all keys have been mutated, rewrite the file.
275 temp_info_plist = tempfile.NamedTemporaryFile()
276 plistlib.writePlist(plist, temp_info_plist.name)
277
278 # Info.plist will work perfectly well in any plist format, but traditionally
279 # applications use xml1 for this, so convert it to ensure that it's valid.
280 output_path = options.plist_path 331 output_path = options.plist_path
281 if options.plist_output is not None: 332 if options.plist_output is not None:
282 output_path = options.plist_output 333 output_path = options.plist_output
283 proc = subprocess.Popen(['plutil', '-convert', 'xml1', 334
284 '-o', output_path, 335 # Now that all keys have been mutated, rewrite the file.
285 temp_info_plist.name]) 336 with tempfile.NamedTemporaryFile() as temp_info_plist:
286 proc.wait() 337 plistlib.writePlist(plist, temp_info_plist.name)
287 return proc.returncode 338
339 # Convert Info.plist to the format requested by the --format flag. Any
340 # format would work on Mac but iOS requires specific format.
341 return _ConvertPlist(temp_info_plist.name, output_path, options.format)
288 342
289 343
290 if __name__ == '__main__': 344 if __name__ == '__main__':
291 sys.exit(Main(sys.argv[1:])) 345 sys.exit(Main(sys.argv[1:]))
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698