#!/usr/bin/env python3 # Copyright (c) 2012 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. """Prints the lowest locally available SDK version greater than or equal to a given minimum sdk version to standard output. Usage: python3 find_sdk.py 10.6 # Ignores SDKs < 10.6 """ import os import re import subprocess import sys from optparse import OptionParser # sdk/build/xcode_links ROOT_SRC_DIR = os.path.join( os.path.dirname( os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) def CreateSymlinkForSDKAt(src, dst): """ Create symlink to Xcode directory at target location, which can be absolute or relative to `ROOT_SRC_DIR`. """ # If `dst` is relative, it is assumed to be relative to src root. if not os.path.isabs(dst): dst = os.path.join(ROOT_SRC_DIR, dst) if not os.path.isdir(dst): os.makedirs(dst) dst = os.path.join(dst, os.path.basename(src)) # Update the symlink if exists. if os.path.islink(dst): current_src = os.readlink(dst) if current_src == src: return dst os.unlink(dst) sys.stderr.write('existing symlink %s points %s; want %s. Removed.' % (dst, current_src, src)) os.symlink(src, dst) return dst def parse_version(version_str): """'10.6' => [10, 6]""" return list(map(int, re.findall(r'(\d+)', version_str))) def main(): parser = OptionParser() parser.add_option( "--verify", action="store_true", dest="verify", default=False, help="return the sdk argument and warn if it doesn't exist") parser.add_option( "--sdk_path", action="store", type="string", dest="sdk_path", default="", help="user-specified SDK path; bypasses verification") parser.add_option( "--print_sdk_path", action="store_true", dest="print_sdk_path", default=False, help="Additionaly print the path the SDK (appears first).") parser.add_option( "--create_symlink_at", action="store", dest="create_symlink_at", help= "Create symlink to SDK at given location and return symlink path as SDK " "info instead of the original location.") (options, args) = parser.parse_args() min_sdk_version = args[0] job = subprocess.Popen(['xcode-select', '-print-path'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True) out, err = job.communicate() if job.returncode != 0: print(out, file=sys.stderr) print(err, file=sys.stderr) raise Exception('Error %d running xcode-select' % job.returncode) sdk_dir = os.path.join(out.rstrip(), 'Platforms/MacOSX.platform/Developer/SDKs') if not os.path.isdir(sdk_dir): raise Exception( 'Install Xcode, launch it, accept the license ' + 'agreement, and run `sudo xcode-select -s /path/to/Xcode.app` ' + 'to continue.') sdks = [ re.findall('^MacOSX(\d+\.\d+)\.sdk$', s) for s in os.listdir(sdk_dir) ] sdks = [s[0] for s in sdks if s] # [['10.5'], ['10.6']] => ['10.5', '10.6'] sdks = [ s for s in sdks # ['10.5', '10.6'] => ['10.6'] if parse_version(s) >= parse_version(min_sdk_version) ] if not sdks: raise Exception('No %s+ SDK found' % min_sdk_version) best_sdk = sorted(sdks, key=parse_version)[0] if options.verify and best_sdk != min_sdk_version and not options.sdk_path: print(''' vvvvvvv This build requires the %s SDK, but it was not found on your system. Either install it, or explicitly set mac_sdk in your GYP_DEFINES. ^^^^^^^' ''' % min_sdk_version, file=sys.stderr) return min_sdk_version if options.print_sdk_path: sdk_path = subprocess.check_output( ['xcodebuild', '-version', '-sdk', 'macosx' + best_sdk, 'Path'], universal_newlines=True).strip() if options.create_symlink_at: print(CreateSymlinkForSDKAt(sdk_path, options.create_symlink_at)) else: print(sdk_path) return best_sdk if __name__ == '__main__': if sys.platform != 'darwin': raise Exception("This script only runs on Mac") print(main())