Skip to content

Commit

Permalink
Fixes to run apple SDK finders as gclient hooks (flutter#825)
Browse files Browse the repository at this point in the history
  • Loading branch information
zanderso committed Feb 29, 2024
1 parent 7b537de commit ebc2748
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 59 deletions.
1 change: 0 additions & 1 deletion build/config/ios/ios_sdk.gni
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ if (ios_sdk_path == "") {
ios_simulator_sdk_path = _ios_sim_sdk_result[0]
}

# Compute default target.
if (use_ios_simulator) {
assert(ios_simulator_sdk_path != "")
ios_sdk_path = ios_simulator_sdk_path
Expand Down
98 changes: 71 additions & 27 deletions build/config/ios/ios_sdk.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,45 +5,89 @@
import argparse
import errno
import os
import shutil
import subprocess
import sys

sys.path.insert(1, '../../build')
sys.path.insert(1, os.path.join(os.path.dirname(__file__), os.pardir, os.pardir))
from pyutil.file_util import symlink

# This script returns the path to the SDK of the given type. Pass the type of
# SDK you want, which is typically 'iphone' or 'iphonesimulator'.
# This script creates symlinks under flutter/prebuilts to the iphone and
# iphone simulator SDKs.

SDKs = ['iphoneos', 'iphonesimulator']

PREBUILTS = os.path.realpath(os.path.join(
os.path.dirname(__file__), os.pardir, os.pardir, os.pardir, 'flutter', 'prebuilts',
))

def main(argv):
parser = argparse.ArgumentParser()
parser.add_argument('--symlink',
help='Whether to create a symlink in the buildroot to the SDK.')
parser.add_argument('--sdk',
choices=['iphoneos', 'iphonesimulator'],
help='Which SDK to find.')
parser.add_argument(
'--as-gclient-hook',
default=False,
action='store_true',
help='Whether the script is running as a gclient hook.',
)
parser.add_argument(
'--symlink',
type=str,
help='Whether to create a symlink in the buildroot to the SDK.',
)
parser.add_argument(
'--sdk',
choices=['iphoneos', 'iphonesimulator'],
help='Which SDK to find.',
)
args = parser.parse_args()

command = [
'xcodebuild',
'-version',
'-sdk',
args.sdk,
'Path'
]

sdk_output = subprocess.check_output(command).decode('utf-8').strip()
if args.symlink:
symlink_target = os.path.join(args.symlink, 'SDKs', os.path.basename(sdk_output))
symlink(sdk_output, symlink_target)
frameworks_location = os.path.join(sdk_output, '..', '..', 'Library', 'Frameworks')
frameworks_symlink = os.path.join(args.symlink, 'Library', 'Frameworks')
symlink(frameworks_location, frameworks_symlink)

sdk_output = symlink_target

print(sdk_output)
# On CI, Xcode is not yet installed when gclient hooks are being run.
# This is because the version of Xcode that CI installs might depend on the
# contents of the repo, so the repo must be set up first, which includes
# running the gclient hooks. Instead, on CI, this script will be run during
# GN.
running_on_luci = os.environ.get('LUCI_CONTEXT') is not None
if running_on_luci and args.as_gclient_hook:
return 0

symlink_path = args.symlink
if not running_on_luci and symlink_path is None:
symlink_path = PREBUILTS

sdks = [args.sdk] if args.sdk is not None else SDKs

sdks_path = None
libraries_path = None
if symlink_path:
sdks_path = os.path.join(symlink_path, 'SDKs')
libraries_path = os.path.join(symlink_path, 'Library')
# Remove any old files created by this script under PREBUILTS/SDKs.
if args.as_gclient_hook:
if os.path.isdir(sdks_path):
shutil.rmtree(sdks_path)
if os.path.isdir(libraries_path):
shutil.rmtree(libraries_path)

for sdk in sdks:
command = [
'xcodebuild',
'-version',
'-sdk',
sdk,
'Path'
]
sdk_output = subprocess.check_output(command).decode('utf-8').strip()
if symlink_path:
symlink_target = os.path.join(sdks_path, os.path.basename(sdk_output))
symlink(sdk_output, symlink_target)
frameworks_location = os.path.join(sdk_output, '..', '..', 'Library', 'Frameworks')
frameworks_symlink = os.path.join(libraries_path, 'Frameworks')
symlink(frameworks_location, frameworks_symlink)
sdk_output = symlink_target
print(sdk_output)
return 0


if __name__ == '__main__':
if sys.platform != 'darwin':
raise Exception('This script only runs on Mac')
Expand Down
7 changes: 5 additions & 2 deletions build/config/mac/mac_sdk.gni
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,21 @@ import("//build/toolchain/rbe.gni")

declare_args() {
# Minimum supported version of the Mac SDK.
mac_sdk_min = "10.14"
mac_sdk_min = ""

# The MACOSX_DEPLOYMENT_TARGET variable used when compiling.
# Must be of the form x.x.x for Info.plist files.
mac_deployment_target = "10.14.0"
mac_deployment_target = ""

# Path to a specific version of the Mac SDK, not including a backslash at
# the end. If empty, the path to the lowest version greater than or equal to
# mac_sdk_min is used.
mac_sdk_path = ""
}

assert(mac_sdk_min != "")
assert(mac_deployment_target != "")

if (mac_sdk_path == "") {
find_sdk_args = []
if ((use_goma || use_rbe) && create_xcode_symlinks) {
Expand Down
55 changes: 26 additions & 29 deletions build/mac/find_sdk.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
sys.path.append(os.path.dirname(os.path.dirname(__file__)))
from pyutil.file_util import symlink

PREBUILTS = os.path.realpath(os.path.join(
os.path.dirname(__file__), os.pardir, os.pardir, 'flutter', 'prebuilts',
))

def parse_version(version_str):
"""'10.6' => [10, 6]"""
Expand All @@ -30,21 +33,31 @@ def parse_version(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("--as-gclient-hook",
action="store_true", dest="as_gclient_hook", default=False,
help="Whether the script is running as a gclient hook.")
parser.add_option("--symlink",
action="store", type="string", dest="symlink", default="",
action="store", type="string", dest="symlink",
help="Whether to create a symlink in the buildroot to the SDK.")
(options, args) = parser.parse_args()
min_sdk_version = args[0]

# On CI, Xcode is not yet installed when gclient hooks are being run.
# This is because the version of Xcode that CI installs might depend on the
# contents of the repo, so the repo must be set up first, which includes
# running the gclient hooks. Instead, on CI, this script will be run during
# GN.
running_on_luci = os.environ.get('LUCI_CONTEXT') is not None
if running_on_luci and options.as_gclient_hook:
return 0

symlink_path = options.symlink
if not running_on_luci and symlink_path is None:
symlink_path = PREBUILTS

job = subprocess.Popen(['xcode-select', '-print-path'],
universal_newlines=True,
stdout=subprocess.PIPE,
Expand Down Expand Up @@ -82,29 +95,13 @@ def main():
print(sdk_json_output)
raise Exception('No %s+ SDK found' % min_sdk_version)

if options.verify and best_sdk != min_sdk_version and not options.sdk_path:
print(sdk_json_output)
sys.stderr.writelines([
'',
' vvvvvvv',
'',
'This build requires the %s SDK, but it was not found on your system.' \
% min_sdk_version,
'Either install it, or explicitly set mac_sdk in your gn args.',
'',
' ^^^^^^^',
''])
return min_sdk_version

if options.symlink or options.print_sdk_path:
if options.symlink:
symlink_target = os.path.join(options.symlink, 'SDKs', os.path.basename(sdk_output))
symlink(sdk_output, symlink_target)
sdk_output = symlink_target

if options.print_sdk_path:
print(sdk_output)
if symlink_path:
sdks_path = os.path.join(symlink_path, 'SDKs')
symlink_target = os.path.join(sdks_path, os.path.basename(sdk_output))
symlink(sdk_output, symlink_target)
sdk_output = symlink_target

print(sdk_output)
return best_sdk


Expand Down

0 comments on commit ebc2748

Please sign in to comment.