1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
|
#!/usr/bin/env python
# Copyright 2016 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.
"""Compress and upload Mac toolchain files.
Stored in in https://pantheon.corp.google.com/storage/browser/chrome-mac-sdk/.
"""
import argparse
import glob
import os
import plistlib
import re
import subprocess
import sys
import tarfile
import tempfile
TOOLCHAIN_URL = "gs://chrome-mac-sdk"
# It's important to at least remove unused Platform folders to cut down on the
# size of the toolchain folder. There are other various unused folders that
# have been removed through trial and error. If future versions of Xcode become
# problematic it's possible this list is incorrect, and can be reduced to just
# the unused platforms. On the flip side, it's likely more directories can be
# excluded.
DEFAULT_EXCLUDE_FOLDERS = [
'Contents/Applications',
'Contents/Developer/Documentation',
'Contents/Developer/Library/Xcode/Templates',
'Contents/Developer/Platforms/AppleTVOS.platform',
'Contents/Developer/Platforms/AppleTVSimulator.platform',
'Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/'
'usr/share/man/',
'Contents/Developer/Platforms/WatchOS.platform',
'Contents/Developer/Platforms/WatchSimulator.platform',
'Contents/Developer/Toolchains/Swift*',
'Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift',
'Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-migrator',
'Contents/Resources/Packages/MobileDevice.pkg',
'Contents/SharedFrameworks/DNTDocumentationSupport.framework'
]
MAC_EXCLUDE_FOLDERS = [
# The only thing we need in iPhoneOS.platform on mac is:
# \Developer\Library\Xcode\PrivatePlugins
# \Info.Plist.
# This is the cleanest way to get these.
'Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Frameworks',
'Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/GPUTools',
'Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/'
'GPUToolsPlatform',
'Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/'
'PrivateFrameworks',
'Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr',
'Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs',
'Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport',
'Contents/Developer/Platforms/iPhoneOS.platform/Library',
'Contents/Developer/Platforms/iPhoneOS.platform/usr',
# iPhoneSimulator has a similar requirement, but the bulk of the binary size is
# in \Developer\SDKs, so only excluding that here.
'Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs',
]
IOS_EXCLUDE_FOLDERS = [
'Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/'
'Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/'
'iPhoneSimulator.sdk/Applications/',
'Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/'
'iPhoneSimulator.sdk/System/Library/AccessibilityBundles/',
'Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/'
'iPhoneSimulator.sdk/System/Library/CoreServices/',
'Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/'
'iPhoneSimulator.sdk/System/Library/LinguisticData/',
]
def main():
"""Compress |target_dir| and upload to |TOOLCHAIN_URL|"""
parser = argparse.ArgumentParser()
parser.add_argument('target_dir',
help="Xcode installation directory.")
parser.add_argument('platform', choices=['ios', 'mac'],
help="Target platform for bundle.")
parser_args = parser.parse_args()
# Verify this looks like an Xcode directory.
contents_dir = os.path.join(parser_args.target_dir, 'Contents')
plist_file = os.path.join(contents_dir, 'version.plist')
try:
info = plistlib.readPlist(plist_file)
except:
print "Invalid Xcode dir."
return 0
build_version = info['ProductBuildVersion']
# Look for previous toolchain tgz files with the same |build_version|.
fname = 'toolchain'
if parser_args.platform == 'ios':
fname = 'ios-' + fname
wildcard_filename = '%s/%s-%s-*.tgz' % (TOOLCHAIN_URL, fname, build_version)
p = subprocess.Popen(['gsutil.py', 'ls', wildcard_filename],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
output = p.communicate()[0]
next_count = 1
if p.returncode == 0:
next_count = len(output.split('\n'))
sys.stdout.write("%s already exists (%s). "
"Do you want to create another? [y/n] "
% (build_version, next_count - 1))
if raw_input().lower() not in set(['yes','y', 'ye']):
print "Skipping duplicate upload."
return 0
os.chdir(parser_args.target_dir)
toolchain_file_name = "%s-%s-%s" % (fname, build_version, next_count)
toolchain_name = tempfile.mktemp(suffix='toolchain.tgz')
print "Creating %s (%s)." % (toolchain_file_name, toolchain_name)
os.environ["COPYFILE_DISABLE"] = "1"
os.environ["GZ_OPT"] = "-8"
args = ['tar', '-cvzf', toolchain_name]
exclude_folders = DEFAULT_EXCLUDE_FOLDERS
if parser_args.platform == 'mac':
exclude_folders += MAC_EXCLUDE_FOLDERS
else:
exclude_folders += IOS_EXCLUDE_FOLDERS
args.extend(map('--exclude={0}'.format, exclude_folders))
args.extend(['.'])
subprocess.check_call(args)
print "Uploading %s toolchain." % toolchain_file_name
destination_path = '%s/%s.tgz' % (TOOLCHAIN_URL, toolchain_file_name)
subprocess.check_call(['gsutil.py', 'cp', '-n', toolchain_name,
destination_path])
print "Done with %s upload." % toolchain_file_name
return 0
if __name__ == '__main__':
sys.exit(main())
|