Pirama Arumuga Nainar | 87d948e | 2016-03-03 15:49:35 -0800 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | # |
| 3 | # Copyright (C) 2015 The Android Open Source Project |
| 4 | # |
| 5 | # Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 | # you may not use this file except in compliance with the License. |
| 7 | # You may obtain a copy of the License at |
| 8 | # |
| 9 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | # |
| 11 | # Unless required by applicable law or agreed to in writing, software |
| 12 | # distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | # See the License for the specific language governing permissions and |
| 15 | # limitations under the License. |
| 16 | # |
| 17 | |
| 18 | """Update the prebuilt clang from the build server.""" |
| 19 | from __future__ import print_function |
| 20 | |
| 21 | import argparse |
| 22 | import inspect |
| 23 | import os |
| 24 | import shutil |
| 25 | import subprocess |
| 26 | import sys |
| 27 | |
| 28 | |
| 29 | THIS_DIR = os.path.realpath(os.path.dirname(__name__)) |
| 30 | ANDROID_DIR = os.path.realpath(os.path.join(THIS_DIR, '../..')) |
| 31 | |
| 32 | BRANCH = 'aosp-llvm' |
| 33 | |
| 34 | |
| 35 | def android_path(*args): |
| 36 | return os.path.join(ANDROID_DIR, *args) |
| 37 | |
| 38 | |
| 39 | class ArgParser(argparse.ArgumentParser): |
| 40 | def __init__(self): |
| 41 | super(ArgParser, self).__init__( |
| 42 | description=inspect.getdoc(sys.modules[__name__])) |
| 43 | |
| 44 | self.add_argument( |
| 45 | 'build', metavar='BUILD', |
| 46 | help='Build number to pull from the build server.') |
| 47 | |
| 48 | self.add_argument( |
| 49 | '-b', '--bug', type=int, |
| 50 | help='Bug to reference in commit message.') |
| 51 | |
| 52 | self.add_argument( |
| 53 | '--use-current-branch', action='store_true', |
| 54 | help='Do not repo start a new branch for the update.') |
| 55 | |
| 56 | |
| 57 | def host_to_build_host(host): |
| 58 | """Gets the build host name for an NDK host tag. |
| 59 | |
| 60 | The Windows builds are done from Linux. |
| 61 | """ |
| 62 | return { |
| 63 | 'darwin': 'mac', |
| 64 | 'linux': 'linux', |
| 65 | 'windows': 'linux', |
| 66 | }[host] |
| 67 | |
| 68 | |
| 69 | def build_name(host): |
| 70 | """Gets the build name for a given host. |
| 71 | |
| 72 | The build name is either "linux" or "darwin", with any Windows builds |
| 73 | coming from "linux". |
| 74 | """ |
| 75 | return { |
| 76 | 'darwin': 'darwin', |
| 77 | 'linux': 'linux', |
| 78 | 'windows': 'linux', |
| 79 | }[host] |
| 80 | |
| 81 | |
Stephen Hines | 8618647 | 2016-08-05 01:16:57 -0700 | [diff] [blame] | 82 | def manifest_name(build_number): |
| 83 | """Returns the manifest file name for a given build. |
| 84 | |
| 85 | >>> manifest_name('1234') |
| 86 | 'manifest_1234.xml' |
| 87 | """ |
| 88 | return 'manifest_{}.xml'.format(build_number) |
| 89 | |
| 90 | |
Pirama Arumuga Nainar | 87d948e | 2016-03-03 15:49:35 -0800 | [diff] [blame] | 91 | def package_name(build_number, host): |
| 92 | """Returns the file name for a given package configuration. |
| 93 | |
| 94 | >>> package_name('1234', 'linux') |
| 95 | 'clang-1234-linux-x86.tar.bz2' |
| 96 | """ |
| 97 | return 'clang-{}-{}-x86.tar.bz2'.format(build_number, host) |
| 98 | |
| 99 | |
| 100 | def download_build(host, build_number, download_dir): |
Stephen Hines | 8618647 | 2016-08-05 01:16:57 -0700 | [diff] [blame] | 101 | filename = package_name(build_number, host) |
| 102 | return download_file(host, build_number, filename, download_dir) |
| 103 | |
| 104 | |
| 105 | def download_manifest(host, build_number, download_dir): |
| 106 | filename = manifest_name(build_number) |
| 107 | return download_file(host, build_number, filename, download_dir) |
| 108 | |
| 109 | |
| 110 | def download_file(host, build_number, pkg_name, download_dir): |
Pirama Arumuga Nainar | 87d948e | 2016-03-03 15:49:35 -0800 | [diff] [blame] | 111 | url_base = 'https://android-build-uber.corp.google.com' |
| 112 | path = 'builds/{branch}-{build_host}-{build_name}/{build_num}'.format( |
| 113 | branch=BRANCH, |
| 114 | build_host=host_to_build_host(host), |
| 115 | build_name=build_name(host), |
| 116 | build_num=build_number) |
| 117 | |
Pirama Arumuga Nainar | 87d948e | 2016-03-03 15:49:35 -0800 | [diff] [blame] | 118 | url = '{}/{}/{}'.format(url_base, path, pkg_name) |
| 119 | |
| 120 | TIMEOUT = '60' # In seconds. |
| 121 | out_file_path = os.path.join(download_dir, pkg_name) |
| 122 | with open(out_file_path, 'w') as out_file: |
| 123 | print('Downloading {} to {}'.format(url, out_file_path)) |
| 124 | subprocess.check_call( |
| 125 | ['sso_client', '--location', '--request_timeout', TIMEOUT, url], |
| 126 | stdout=out_file) |
| 127 | return out_file_path |
| 128 | |
| 129 | |
| 130 | def extract_package(package, install_dir): |
| 131 | cmd = ['tar', 'xf', package, '-C', install_dir] |
| 132 | print('Extracting {}...'.format(package)) |
| 133 | subprocess.check_call(cmd) |
| 134 | |
| 135 | |
| 136 | def update_clang(host, build_number, use_current_branch, download_dir, bug): |
| 137 | host_tag = host + '-x86' |
| 138 | prebuilt_dir = android_path('prebuilts/clang/host', host_tag) |
| 139 | os.chdir(prebuilt_dir) |
| 140 | |
| 141 | if not use_current_branch: |
| 142 | subprocess.check_call( |
| 143 | ['repo', 'start', 'update-clang-{}'.format(build_number), '.']) |
| 144 | |
| 145 | package = download_build(host, build_number, download_dir) |
Stephen Hines | 8618647 | 2016-08-05 01:16:57 -0700 | [diff] [blame] | 146 | manifest = download_manifest(host, build_number, download_dir) |
Pirama Arumuga Nainar | 87d948e | 2016-03-03 15:49:35 -0800 | [diff] [blame] | 147 | |
| 148 | install_subdir = 'clang-' + build_number |
| 149 | extract_package(package, prebuilt_dir) |
Stephen Hines | 8618647 | 2016-08-05 01:16:57 -0700 | [diff] [blame] | 150 | shutil.copy(manifest, prebuilt_dir + '/' + install_subdir) |
Pirama Arumuga Nainar | 87d948e | 2016-03-03 15:49:35 -0800 | [diff] [blame] | 151 | |
| 152 | print('Adding files to index...') |
| 153 | subprocess.check_call(['git', 'add', install_subdir]) |
| 154 | |
| 155 | version_file_path = os.path.join(install_subdir, 'AndroidVersion.txt') |
| 156 | with open(version_file_path) as version_file: |
| 157 | version = version_file.read().strip() |
| 158 | |
| 159 | print('Committing update...') |
| 160 | message_lines = [ |
| 161 | 'Update prebuilt Clang to build {}.'.format(build_number), |
| 162 | '', |
| 163 | 'Built from version {}.'.format(version), |
| 164 | ] |
| 165 | if bug is not None: |
| 166 | message_lines.append('') |
| 167 | message_lines.append('Bug: http://b/{}'.format(bug)) |
| 168 | message = '\n'.join(message_lines) |
| 169 | subprocess.check_call(['git', 'commit', '-m', message]) |
| 170 | |
| 171 | |
| 172 | def main(): |
| 173 | args = ArgParser().parse_args() |
| 174 | |
| 175 | download_dir = os.path.realpath('.download') |
| 176 | if os.path.isdir(download_dir): |
| 177 | shutil.rmtree(download_dir) |
| 178 | os.makedirs(download_dir) |
| 179 | |
| 180 | try: |
| 181 | hosts = ('darwin', 'linux', 'windows') |
| 182 | for host in hosts: |
| 183 | update_clang(host, args.build, args.use_current_branch, |
| 184 | download_dir, args.bug) |
| 185 | finally: |
| 186 | shutil.rmtree(download_dir) |
| 187 | |
| 188 | |
| 189 | if __name__ == '__main__': |
| 190 | main() |