| #!/usr/bin/env python |
| # -*- coding: utf-8 -*- |
| # |
| # Copyright (C) 2019 Apple Inc. All rights reserved. |
| # |
| # Redistribution and use in source and binary forms, with or without |
| # modification, are permitted provided that the following conditions |
| # are met: |
| # |
| # 1. Redistributions of source code must retain the above copyright |
| # notice, this list of conditions and the following disclaimer. |
| # 2. Redistributions in binary form must reproduce the above copyright |
| # notice, this list of conditions and the following disclaimer in the |
| # documentation and/or other materials provided with the distribution. |
| # |
| # THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
| # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
| # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| |
| # Class for representing SDK information, in the form of Platform, Version, and |
| # whether or not it's an Internal SDK. This class also contains a factory |
| # method for producing an SDK instance from a "specification" string such as |
| # "macOS15.3Internal", like you would get from 'xcodebuild -showsdks". |
| |
| |
| import re |
| |
| from webkitpy.common.system.executive import Executive |
| |
| |
| test_output = None |
| |
| |
| class SDK(object): |
| __slots__ = ["xcode_specification", "platform", "version", "internal"] |
| |
| def __init__(self, xcode_specification, platform, version, internal): |
| super(SDK, self).__init__() |
| self.xcode_specification = xcode_specification |
| self.platform = platform |
| self.version = version |
| self.internal = internal |
| |
| def __repr__(self): |
| return "SDK({}, {}, {}, {})".format( |
| self.xcode_specification, |
| self.platform, |
| self.version, |
| self.internal) |
| |
| def as_xcode_specification(self): |
| return "{}.internal".format(self.platform) if self.internal else self.platform |
| |
| @classmethod |
| def get_preferred_sdk_for_platform(cls, platform, executive=None): |
| |
| preferred_sdk = cls._parse_sdk(platform) |
| |
| executive = executive or Executive() |
| stdout = executive.run_command(["xcodebuild", "-showsdks"]) |
| |
| for line in stdout.splitlines(): |
| m = re.match(r".*-sdk (.*)", line) |
| if m: |
| this_sdk = cls._parse_sdk(m.group(1)) |
| |
| if preferred_sdk.platform != this_sdk.platform: |
| continue |
| |
| # Both have version information, so compare versions. If the |
| # versions are equal, prefer the Internal sdk. Otherwise, keep |
| # the one with the higher version. |
| |
| if preferred_sdk.version and this_sdk.version: |
| if float(preferred_sdk.version) == float(this_sdk.version): |
| if this_sdk.internal: |
| preferred_sdk = this_sdk |
| elif float(preferred_sdk.version) < float(this_sdk.version): |
| preferred_sdk = this_sdk |
| |
| # The preferred sdk does not have a version but the prospective |
| # one does, so keep the prospective one. |
| |
| elif not preferred_sdk.version and this_sdk.version: |
| preferred_sdk = this_sdk |
| |
| # The preferred sdk has a version but the prospective one does |
| # not, so keep the preferred one. |
| |
| elif preferred_sdk.version and not this_sdk.version: |
| pass |
| |
| # Neither has version information; prefer the current one if |
| # it's internal. |
| |
| elif not preferred_sdk.version and not this_sdk.version: |
| if this_sdk.internal: |
| preferred_sdk = this_sdk |
| |
| return preferred_sdk |
| |
| @classmethod |
| def _parse_sdk(cls, xcode_specification): |
| # letters-and-dots, followed by optional numbers-and-dots, followed by |
| # an optional "internal" |
| m = re.match(r"([a-zA-Z.]+[a-zA-Z])([0-9.]+[0-9])?\.?(internal)?", xcode_specification) |
| if not m: |
| return SDK(xcode_specification, None, None, None) |
| |
| platform = m.group(1) |
| version = m.group(2) |
| internal = m.group(3) |
| |
| return SDK(xcode_specification, platform, version, internal) |