Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 #!/usr/bin/env python | |
| 2 # Copyright 2016 The Chromium Authors. All rights reserved. | |
| 3 # Use of this source code is governed by a BSD-style license that can be | |
| 4 # found in the LICENSE file. | |
| 5 | |
| 6 """Download necessary mac toolchain files under certain conditions. If | |
| 7 xcode-select is already set and points to an external folder | |
| 8 (e.g. /Application/Xcode.app), this script only runs if the GYP_DEFINE | |
| 9 |force_mac_toolchain| is set. To override the values in | |
| 10 |TOOLCHAIN_REVISION|-|TOOLCHAIN_SUB_REVISION| below, GYP_DEFINE | |
| 11 mac_toolchain_revision can be used instead. | |
| 12 | |
| 13 This script will only run on machines if /usr/bin/xcodebuild has been added to | |
| 14 the sudoers list so the license can be accepted. | |
| 15 | |
| 16 Otherwise, user input would be required to complete the script. Perhaps future | |
| 17 versions can be modified to allow for user input on developer machines. | |
| 18 """ | |
| 19 | |
| 20 import os | |
| 21 import shutil | |
| 22 import subprocess | |
| 23 import sys | |
| 24 import tarfile | |
| 25 import time | |
| 26 import tempfile | |
| 27 import urllib2 | |
| 28 | |
| 29 # Update sys.path to import gyp. | |
| 30 script_dir = os.path.dirname(os.path.realpath(__file__)) | |
| 31 chrome_src = os.path.abspath(os.path.join(script_dir, os.pardir)) | |
| 32 sys.path.insert(0, os.path.join(chrome_src, 'tools', 'gyp', 'pylib')) | |
| 33 import gyp | |
| 34 | |
| 35 # This can be changed after running /build/package_mac_toolchain.py. | |
| 36 TOOLCHAIN_REVISION = '5B1008' | |
| 37 TOOLCHAIN_SUB_REVISION = 2 | |
| 38 TOOLCHAIN_VERSION = '%s-%s' % (TOOLCHAIN_REVISION, TOOLCHAIN_SUB_REVISION) | |
| 39 | |
| 40 BASE_DIR = os.path.abspath(os.path.dirname(__file__)) | |
| 41 TOOLCHAIN_BUILD_DIR = os.path.join(BASE_DIR, 'mac_files', 'Xcode.app') | |
| 42 STAMP_FILE = os.path.join(BASE_DIR, 'mac_files', 'toolchain_build_revision') | |
| 43 TOOLCHAIN_URL = 'gs://chrome-mac-sdk/' | |
| 44 | |
| 45 | |
| 46 def SetEnvironment(): | |
| 47 if sys.platform == 'darwin' and not UseLocalMacSDK(): | |
| 48 os.environ['DEVELOPER_DIR'] = TOOLCHAIN_BUILD_DIR | |
| 49 | |
| 50 | |
| 51 def ReadStampFile(): | |
| 52 """Return the contents of the stamp file, or '' if it doesn't exist.""" | |
| 53 try: | |
| 54 with open(STAMP_FILE, 'r') as f: | |
| 55 return f.read().rstrip() | |
| 56 except IOError: | |
| 57 return '' | |
| 58 | |
| 59 | |
| 60 def WriteStampFile(s): | |
| 61 """Write s to the stamp file.""" | |
| 62 EnsureDirExists(os.path.dirname(STAMP_FILE)) | |
| 63 with open(STAMP_FILE, 'w') as f: | |
| 64 f.write(s) | |
| 65 f.write('\n') | |
| 66 | |
| 67 | |
| 68 def EnsureDirExists(path): | |
| 69 if not os.path.exists(path): | |
| 70 os.makedirs(path) | |
| 71 | |
| 72 | |
| 73 def DownloadAndUnpack(url, output_dir): | |
| 74 """Decompresses |url| into a cleared |output_dir|.""" | |
| 75 temp_name = tempfile.mktemp(prefix='mac_toolchain') | |
| 76 try: | |
| 77 print 'Downloading new toolchain.' | |
| 78 subprocess.check_call(['gsutil.py', 'cp', url, temp_name]) | |
| 79 if os.path.exists(output_dir): | |
| 80 print 'Deleting old toolchain.' | |
| 81 shutil.rmtree(output_dir) | |
| 82 EnsureDirExists(output_dir) | |
| 83 print 'Unpacking new toolchain.' | |
| 84 tarfile.open(mode='r:gz', name=temp_name).extractall(path=output_dir) | |
| 85 finally: | |
| 86 if os.path.exists(temp_name): | |
| 87 os.unlink(temp_name) | |
| 88 | |
| 89 | |
| 90 def CanAccessToolchainBucket(): | |
| 91 """Checks whether the user has access to |TOOLCHAIN_URL|.""" | |
| 92 proc = subprocess.Popen(['gsutil.py', 'ls', TOOLCHAIN_URL], | |
| 93 stdout=subprocess.PIPE) | |
| 94 proc.communicate() | |
| 95 return proc.returncode == 0 | |
| 96 | |
| 97 | |
| 98 def SwitchToolchain(directory): | |
|
Nico
2016/03/22 20:59:05
Rename to AcceptLicense
justincohen
2016/03/23 17:12:44
Done.
| |
| 99 """Use xcodebuild to accept new toolchain license. This only | |
| 100 works if xcodebuild is in sudoers.""" | |
| 101 xcodebuild = os.path.join(TOOLCHAIN_BUILD_DIR, | |
| 102 'Contents/Developer/usr/bin/xcodebuild') | |
| 103 subprocess.check_call(['sudo', xcodebuild, '-license', 'accept']) | |
| 104 | |
| 105 | |
| 106 def UseLocalMacSDK(): | |
| 107 gyp_defines = gyp.NameValueListToDict(gyp.ShlexEnv('GYP_DEFINES')) | |
| 108 force_pull = 'force_mac_toolchain' in gyp_defines | |
|
Nico
2016/03/22 20:59:05
Hm, this won't work with gn. Is there an advantage
justincohen
2016/03/23 17:12:44
Changed to environ FORCE_MAC_TOOLCHAIN
| |
| 109 | |
| 110 # Don't update the toolchain if there's already one installed outside of the | |
| 111 # expected location for a Chromium mac toolchain, unless |force_pull| is set. | |
| 112 proc = subprocess.Popen(['xcode-select', '-p'], stdout=subprocess.PIPE) | |
| 113 xcode_select_dir = proc.communicate()[0] | |
| 114 rc = proc.returncode | |
| 115 return (not force_pull and rc == 0 and | |
| 116 TOOLCHAIN_BUILD_DIR not in xcode_select_dir) | |
| 117 | |
| 118 | |
| 119 def main(): | |
| 120 if sys.platform != 'darwin': | |
| 121 return 0 | |
| 122 | |
| 123 # TODO(justincohen): Add support for GN per crbug.com/570091 | |
| 124 if UseLocalMacSDK(): | |
| 125 print 'Using local toolchain.' | |
| 126 return 0 | |
| 127 | |
| 128 gyp_defines = gyp.NameValueListToDict(gyp.ShlexEnv('GYP_DEFINES')) | |
| 129 toolchain_revision = gyp_defines.get('mac_toolchain_revision', | |
|
Nico
2016/03/22 20:59:05
same question here
justincohen
2016/03/23 17:12:44
Changed to environ MAC_TOOLCHAIN_REVISION
| |
| 130 TOOLCHAIN_VERSION) | |
| 131 if ReadStampFile() == toolchain_revision: | |
| 132 print 'Toolchain (%s) is already up to date.' % toolchain_revision | |
| 133 SwitchToolchain(TOOLCHAIN_BUILD_DIR) | |
| 134 return 0 | |
| 135 | |
| 136 if not CanAccessToolchainBucket(): | |
| 137 print 'Cannot access toolchain bucket.' | |
| 138 return 0 | |
| 139 | |
| 140 # Reset the stamp file in case the build is unsuccessful. | |
| 141 WriteStampFile('') | |
| 142 | |
| 143 toolchain_file = '%s.tgz' % toolchain_revision | |
| 144 toolchain_full_url = TOOLCHAIN_URL + toolchain_file | |
| 145 | |
| 146 print 'Updating toolchain to %s...' % toolchain_revision | |
| 147 try: | |
| 148 toolchain_file = 'toolchain-%s.tgz' % toolchain_revision | |
| 149 toolchain_full_url = TOOLCHAIN_URL + toolchain_file | |
| 150 DownloadAndUnpack(toolchain_full_url, TOOLCHAIN_BUILD_DIR) | |
| 151 SwitchToolchain(TOOLCHAIN_BUILD_DIR) | |
| 152 | |
| 153 print 'Toolchain %s unpacked.' % toolchain_revision | |
| 154 WriteStampFile(toolchain_revision) | |
| 155 return 0 | |
| 156 except: | |
| 157 print 'Failed to download toolchain %s.' % toolchain_file | |
| 158 print 'Exiting.' | |
| 159 return 1 | |
| 160 | |
| 161 if __name__ == '__main__': | |
| 162 sys.exit(main()) | |
| OLD | NEW |