1# Copyright 2018 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4"""The `macos_sdk` module provides safe functions to access a semi-hermetic 5XCode installation. 6 7Available only to Google-run bots.""" 8 9from contextlib import contextmanager 10 11from recipe_engine import recipe_api 12 13 14class MacOSSDKApi(recipe_api.RecipeApi): 15 """API for using OS X SDK distributed via CIPD.""" 16 17 def __init__(self, sdk_properties, *args, **kwargs): 18 super(MacOSSDKApi, self).__init__(*args, **kwargs) 19 20 self._sdk_version = sdk_properties['sdk_version'].lower() 21 self._tool_package = sdk_properties['tool_package'] 22 self._tool_version = sdk_properties['tool_version'] 23 24 @contextmanager 25 def __call__(self): 26 """Sets up the XCode SDK environment. 27 28 This call is a no-op on non-Mac platforms. 29 30 This will deploy the helper tool and the XCode.app bundle at 31 `[START_DIR]/cache/macos_sdk`. 32 33 To avoid machines rebuilding these on every run, set up a named cache in 34 your cr-buildbucket.cfg file like: 35 36 caches: { 37 # Cache for mac_toolchain tool and XCode.app 38 name: "macos_sdk" 39 path: "macos_sdk" 40 } 41 42 If you have builders which e.g. use a non-current SDK, you can give them 43 a uniqely named cache: 44 45 caches: { 46 # Cache for N-1 version mac_toolchain tool and XCode.app 47 name: "macos_sdk_old" 48 path: "macos_sdk" 49 } 50 51 Usage: 52 with api.macos_sdk(): 53 # sdk with mac build bits 54 55 Raises: 56 StepFailure or InfraFailure. 57 """ 58 if not self.m.platform.is_mac: 59 yield 60 return 61 62 try: 63 with self.m.context(infra_steps=True): 64 sdk_dir = self._ensure_sdk() 65 self.m.step('select XCode', 66 ['sudo', 'xcode-select', '--switch', sdk_dir]) 67 yield 68 finally: 69 with self.m.context(infra_steps=True): 70 self.m.step('reset XCode', ['sudo', 'xcode-select', '--reset']) 71 72 def _ensure_sdk(self): 73 """Ensures the mac_toolchain tool and MacOS SDK packages are installed. 74 75 Returns Path to the installed sdk app bundle.""" 76 cache_dir = self.m.path['cache'].join('macos_sdk') 77 pkgs = self.m.cipd.EnsureFile() 78 pkgs.add_package(self._tool_package, self._tool_version) 79 self.m.cipd.ensure(cache_dir, pkgs) 80 81 sdk_dir = cache_dir.join('XCode.app') 82 self.m.step('install xcode', [ 83 cache_dir.join('mac_toolchain'), 84 'install', 85 '-kind', 86 'mac', 87 '-xcode-version', 88 self._sdk_version, 89 '-output-dir', 90 sdk_dir, 91 ]) 92 return sdk_dir 93