1#!/usr/bin/env python 2# -*- coding: utf-8 -*- 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 5# found in the LICENSE file. 6 7"""Prints the lowest locally available SDK version greater than or equal to a 8given minimum sdk version to standard output. If --developer_dir is passed, then 9the script will use the Xcode toolchain located at DEVELOPER_DIR. 10 11Usage: 12 python find_sdk.py [--developer_dir DEVELOPER_DIR] 10.6 # Ignores SDKs < 10.6 13""" 14 15import os 16import re 17import subprocess 18import sys 19 20from optparse import OptionParser 21 22 23class SdkError(Exception): 24 def __init__(self, value): 25 self.value = value 26 27 def __str__(self): 28 return repr(self.value) 29 30 31def parse_version(version_str): 32 """'10.6' => [10, 6]""" 33 return map(int, re.findall(r'(\d+)', version_str)) 34 35 36def main(): 37 parser = OptionParser() 38 parser.add_option("--verify", 39 action="store_true", dest="verify", default=False, 40 help="return the sdk argument and warn if it doesn't exist") 41 parser.add_option("--sdk_path", 42 action="store", type="string", dest="sdk_path", 43 default="", 44 help="user-specified SDK path; bypasses verification") 45 parser.add_option("--print_sdk_path", 46 action="store_true", dest="print_sdk_path", default=False, 47 help="Additionally print the path the SDK (appears first).") 48 parser.add_option("--developer_dir", help='Path to Xcode.') 49 options, args = parser.parse_args() 50 if len(args) != 1: 51 parser.error('Please specify a minimum SDK version') 52 min_sdk_version = args[0] 53 54 if options.developer_dir: 55 os.environ['DEVELOPER_DIR'] = options.developer_dir 56 57 job = subprocess.Popen(['xcode-select', '-print-path'], 58 stdout=subprocess.PIPE, 59 stderr=subprocess.STDOUT) 60 out, err = job.communicate() 61 if job.returncode != 0: 62 print(out, file=sys.stderr) 63 print(err, file=sys.stderr) 64 raise Exception('Error %d running xcode-select' % job.returncode) 65 sdk_dir = os.path.join( 66 str(out.rstrip(), encoding="utf-8"), 67 'Platforms/MacOSX.platform/Developer/SDKs') 68 # Xcode must be installed, its license agreement must be accepted, and its 69 # command-line tools must be installed. Stand-alone installations (in 70 # /Library/Developer/CommandLineTools) are not supported. 71 # https://bugs.chromium.org/p/chromium/issues/detail?id=729990#c1 72 file_path = os.path.relpath("/path/to/Xcode.app") 73 if not os.path.isdir(sdk_dir) or not '.app/Contents/Developer' in sdk_dir: 74 raise SdkError('Install Xcode, launch it, accept the license ' + 75 'agreement, and run `sudo xcode-select -s %s` ' % file_path + 76 'to continue.') 77 sdks = [re.findall('^MacOSX(1[0,1,2,3,4]\.\d+)\.sdk$', s) for s in 78 os.listdir(sdk_dir)] 79 sdks = [s[0] for s in sdks if s] # [['10.5'], ['10.6']] => ['10.5', '10.6'] 80 sdks = [s for s in sdks # ['10.5', '10.6'] => ['10.6'] 81 if list(parse_version(s)) >= list(parse_version(min_sdk_version))] 82 83 if not sdks: 84 raise Exception('No %s+ SDK found' % min_sdk_version) 85 best_sdk = sorted(sdks)[0] 86 87 if options.verify and best_sdk != min_sdk_version and not options.sdk_path: 88 print('', file=sys.stderr) 89 print(' vvvvvvv', 90 file=sys.stderr) 91 print('', file=sys.stderr) 92 print( 93 'This build requires the %s SDK, but it was not found on your system.' \ 94 % min_sdk_version, file=sys.stderr) 95 print( 96 'Either install it, or explicitly set mac_sdk in your GYP_DEFINES.', 97 file=sys.stderr) 98 print('', file=sys.stderr) 99 print(' ^^^^^^^', 100 file=sys.stderr) 101 print('', file=sys.stderr) 102 sys.exit(1) 103 104 if options.print_sdk_path: 105 _sdk_path = subprocess.check_output( 106 ['xcrun', '-sdk', 'macosx' + best_sdk, '--show-sdk-path']).strip() 107 if isinstance(_sdk_path, bytes): 108 _sdk_path = _sdk_path.decode() 109 print(_sdk_path) 110 return best_sdk 111 112 113if __name__ == '__main__': 114 if sys.platform != 'darwin': 115 raise Exception("This script only runs on Mac") 116 print(main()) 117 sys.exit(0) 118