blob: c8f55cb475b22af4a04458e900198041de20c675 [file] [log] [blame]
# Copyright 2019 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.
"""Collects information about the SDK and return them as JSON file."""
import argparse
import json
import os
import re
import subprocess
import sys
# Patterns used to extract the Xcode version and build version.
XCODE_VERSION_PATTERN = re.compile(r'Xcode (\d+)\.(\d+)')
XCODE_BUILD_PATTERN = re.compile(r'Build version (.*)')
def GetCommandOutput(command):
"""Returns the output of `command` as a string."""
return subprocess.check_output(command, encoding='utf-8')
def GetAppleCpuName(target_cpu):
"""Returns the name of the |target_cpu| using Apple's convention."""
return {
'x64': 'x86_64',
'arm': 'armv7',
'x86': 'i386'
}.get(target_cpu, target_cpu)
def GetPlatform(target_environment):
"""Returns the platform for |target_environment|."""
return {
'simulator': 'iphonesimulator',
'device': 'iphoneos'
def GetPlaformDisplayName(target_environment):
"""Returns the platform display name for |target_environment|."""
return {
'simulator': 'iPhoneSimulator',
'device': 'iPhoneOS'
def ExtractOSVersion():
"""Extract the version of macOS of the current machine."""
return GetCommandOutput(['sw_vers', '-buildVersion']).strip()
def ExtractXcodeInfo():
"""Extract Xcode version and build version."""
version, build = None, None
for line in GetCommandOutput(['xcodebuild', '-version']).splitlines():
match =
if match:
major, minor =,
version = major.rjust(2, '0') + minor.ljust(2, '0')
match =
if match:
build =
assert version is not None and build is not None
return version, build
def ExtractSDKInfo(info, sdk):
"""Extract information about the SDK."""
return GetCommandOutput(['xcrun', '--sdk', sdk, '--show-sdk-' + info]).strip()
def GetDeveloperDir():
"""Returns the developer dir."""
return GetCommandOutput(['xcode-select', '-print-path']).strip()
def GetSDKInfoForCpu(target_cpu, environment, sdk_version, deployment_target):
"""Returns a dictionary with information about the SDK."""
platform = GetPlatform(environment)
sdk_version = sdk_version or ExtractSDKInfo('version', platform)
deployment_target = deployment_target or sdk_version
target = target_cpu + '-apple-ios' + deployment_target
if environment == 'simulator':
target = target + '-simulator'
xcode_version, xcode_build = ExtractXcodeInfo()
effective_sdk = platform + sdk_version
sdk_info = {}
sdk_info['compiler'] = ''
sdk_info['is_simulator'] = environment == 'simulator'
sdk_info['macos_build'] = ExtractOSVersion()
sdk_info['platform'] = platform
sdk_info['platform_name'] = GetPlaformDisplayName(environment)
sdk_info['sdk'] = effective_sdk
sdk_info['sdk_build'] = ExtractSDKInfo('build-version', effective_sdk)
sdk_info['sdk_path'] = ExtractSDKInfo('path', effective_sdk)
sdk_info['toolchain_path'] = os.path.join(
GetDeveloperDir(), 'Toolchains/XcodeDefault.xctoolchain')
sdk_info['sdk_version'] = sdk_version
sdk_info['target'] = target
sdk_info['xcode_build'] = xcode_build
sdk_info['xcode_version'] = xcode_version
return sdk_info
def ParseArgs(argv):
"""Parses command line arguments."""
parser = argparse.ArgumentParser(
'-t', '--target-cpu', default='x64',
choices=('x86', 'x64', 'arm', 'arm64'),
help='target cpu')
choices=('simulator', 'device'),
help='target environment')
'-s', '--sdk-version',
help='version of the sdk')
'-d', '--deployment-target',
help='iOS deployment target')
'-o', '--output', default='-',
help='path of the output file to create; - means stdout')
return parser.parse_args(argv)
def main(argv):
args = ParseArgs(argv)
sdk_info = GetSDKInfoForCpu(
GetAppleCpuName(args.target_cpu), args.target_environment,
args.sdk_version, args.deployment_target)
if args.output == '-':
with open(args.output, 'w') as output:
if __name__ == '__main__':