Home | History | Annotate | Download | only in clang
      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 
     82 def package_name(build_number, host):
     83     """Returns the file name for a given package configuration.
     84 
     85     >>> package_name('1234', 'linux')
     86     'clang-1234-linux-x86.tar.bz2'
     87     """
     88     return 'clang-{}-{}-x86.tar.bz2'.format(build_number, host)
     89 
     90 
     91 def download_build(host, build_number, download_dir):
     92     url_base = 'https://android-build-uber.corp.google.com'
     93     path = 'builds/{branch}-{build_host}-{build_name}/{build_num}'.format(
     94         branch=BRANCH,
     95         build_host=host_to_build_host(host),
     96         build_name=build_name(host),
     97         build_num=build_number)
     98 
     99     pkg_name = package_name(build_number, host)
    100     url = '{}/{}/{}'.format(url_base, path, pkg_name)
    101 
    102     TIMEOUT = '60'  # In seconds.
    103     out_file_path = os.path.join(download_dir, pkg_name)
    104     with open(out_file_path, 'w') as out_file:
    105         print('Downloading {} to {}'.format(url, out_file_path))
    106         subprocess.check_call(
    107             ['sso_client', '--location', '--request_timeout', TIMEOUT, url],
    108             stdout=out_file)
    109     return out_file_path
    110 
    111 
    112 def extract_package(package, install_dir):
    113     cmd = ['tar', 'xf', package, '-C', install_dir]
    114     print('Extracting {}...'.format(package))
    115     subprocess.check_call(cmd)
    116 
    117 
    118 def update_clang(host, build_number, use_current_branch, download_dir, bug):
    119     host_tag = host + '-x86'
    120     prebuilt_dir = android_path('prebuilts/clang/host', host_tag)
    121     os.chdir(prebuilt_dir)
    122 
    123     if not use_current_branch:
    124         subprocess.check_call(
    125             ['repo', 'start', 'update-clang-{}'.format(build_number), '.'])
    126 
    127     package = download_build(host, build_number, download_dir)
    128 
    129     install_subdir = 'clang-' + build_number
    130     extract_package(package, prebuilt_dir)
    131 
    132     print('Adding files to index...')
    133     subprocess.check_call(['git', 'add', install_subdir])
    134 
    135     version_file_path = os.path.join(install_subdir, 'AndroidVersion.txt')
    136     with open(version_file_path) as version_file:
    137         version = version_file.read().strip()
    138 
    139     print('Committing update...')
    140     message_lines = [
    141         'Update prebuilt Clang to build {}.'.format(build_number),
    142         '',
    143         'Built from version {}.'.format(version),
    144     ]
    145     if bug is not None:
    146         message_lines.append('')
    147         message_lines.append('Bug: http://b/{}'.format(bug))
    148     message = '\n'.join(message_lines)
    149     subprocess.check_call(['git', 'commit', '-m', message])
    150 
    151 
    152 def main():
    153     args = ArgParser().parse_args()
    154 
    155     download_dir = os.path.realpath('.download')
    156     if os.path.isdir(download_dir):
    157         shutil.rmtree(download_dir)
    158     os.makedirs(download_dir)
    159 
    160     try:
    161         hosts = ('darwin', 'linux', 'windows')
    162         for host in hosts:
    163             update_clang(host, args.build, args.use_current_branch,
    164                          download_dir, args.bug)
    165     finally:
    166         shutil.rmtree(download_dir)
    167 
    168 
    169 if __name__ == '__main__':
    170     main()
    171