|
25 | 25 | import json
|
26 | 26 | import os
|
27 | 27 | import pipes
|
| 28 | +import plistlib |
28 | 29 | import re
|
29 | 30 | import shutil
|
30 | 31 | import signal
|
@@ -340,17 +341,39 @@ def _GetXcodeBuildVersionString():
|
340 | 341 |
|
341 | 342 | @staticmethod
|
342 | 343 | def _GetXcodeVersionString():
|
343 |
| - """Returns Xcode version info from the environment as a string.""" |
344 |
| - reported_version = os.environ['XCODE_VERSION_ACTUAL'] |
345 |
| - match = re.match(r'(\d{2})(\d)(\d)$', reported_version) |
346 |
| - if not match: |
347 |
| - _PrintUnbuffered('Warning: Failed to extract Xcode version from %s' % ( |
348 |
| - reported_version)) |
| 344 | + """Returns Xcode version info from the Xcode's version.plist. |
| 345 | +
|
| 346 | + Just reading XCODE_VERSION_ACTUAL from the environment seems like |
| 347 | + a more reasonable implementation, but has shown to be unreliable, |
| 348 | + at least when using Xcode 11.3.1 and opening the project within an |
| 349 | + Xcode workspace. |
| 350 | + """ |
| 351 | + developer_dir = os.environ['DEVELOPER_DIR'] |
| 352 | + app_dir = developer_dir.split('.app')[0] + '.app' |
| 353 | + version_plist_path = os.path.join(app_dir, 'Contents', 'version.plist') |
| 354 | + try: |
| 355 | + # python2 API to plistlib - needs updating if/when Tulsi bumps to python3 |
| 356 | + plist = plistlib.readPlist(version_plist_path) |
| 357 | + except IOError: |
| 358 | + _PrintXcodeWarning('Tulsi cannot determine Xcode version, error ' |
| 359 | + 'reading from {}'.format(version_plist_path)) |
349 | 360 | return None
|
350 |
| - major_version = int(match.group(1)) |
351 |
| - minor_version = int(match.group(2)) |
352 |
| - fix_version = int(match.group(3)) |
353 |
| - return '%d.%d.%d' % (major_version, minor_version, fix_version) |
| 361 | + try: |
| 362 | + # Example: "11.3.1", "11.3", "11.0" |
| 363 | + key = 'CFBundleShortVersionString' |
| 364 | + version_string = plist[key] |
| 365 | + except KeyError: |
| 366 | + _PrintXcodeWarning('Tulsi cannot determine Xcode version from {}, no ' |
| 367 | + '"{}" key'.format(version_plist_path, key)) |
| 368 | + return None |
| 369 | + |
| 370 | + # But we need to normalize to major.minor.patch, e.g. 11.3.0 or |
| 371 | + # 11.0.0, so add one or two ".0" if needed (two just in case |
| 372 | + # there is ever just a single version number like "12") |
| 373 | + dots_count = version_string.count('.') |
| 374 | + dot_zeroes_to_add = 2 - dots_count |
| 375 | + version_string += '.0' * dot_zeroes_to_add |
| 376 | + return version_string |
354 | 377 |
|
355 | 378 | @staticmethod
|
356 | 379 | def _ComputeXcodeVersionFlag():
|
|
0 commit comments