1#!/usr/bin/env python
2"""Downloads a prebuilt gn binary to a place where gn.py can find it."""
3
4from __future__ import print_function
5
6import io
7import os
8try:
9    # In Python 3, we need the module urllib.reqest. In Python 2, this
10    # functionality was in the urllib2 module.
11    from urllib import request as urllib_request
12except ImportError:
13    import urllib2 as urllib_request
14import sys
15import zipfile
16
17
18def download_and_unpack(url, output_dir, gn):
19    """Download an archive from url and extract gn from it into output_dir."""
20    print('downloading %s ...' % url, end='')
21    sys.stdout.flush()
22    data = urllib_request.urlopen(url).read()
23    print(' done')
24    zipfile.ZipFile(io.BytesIO(data)).extract(gn, path=output_dir)
25
26
27def set_executable_bit(path):
28    mode = os.stat(path).st_mode
29    mode |= (mode & 0o444) >> 2 # Copy R bits to X.
30    os.chmod(path, mode) # No-op on Windows.
31
32
33def get_platform():
34    import platform
35    if sys.platform == 'darwin':
36        return 'mac-amd64' if platform.machine() != 'arm64' else 'mac-arm64'
37    if platform.machine() not in ('AMD64', 'x86_64'):
38        return None
39    if sys.platform.startswith('linux'):
40        return 'linux-amd64'
41    if sys.platform == 'win32':
42        return 'windows-amd64'
43
44
45def main():
46    platform = get_platform()
47    if not platform:
48        print('no prebuilt binary for', sys.platform)
49        print('build it yourself with:')
50        print('  rm -rf /tmp/gn &&')
51        print('  pushd /tmp && git clone https://gn.googlesource.com/gn &&')
52        print('  cd gn && build/gen.py && ninja -C out gn && popd &&')
53        print('  cp /tmp/gn/out/gn somewhere/on/PATH')
54        return 1
55    dirname = os.path.join(os.path.dirname(__file__), 'bin', platform)
56    if not os.path.exists(dirname):
57        os.makedirs(dirname)
58
59    url = 'https://chrome-infra-packages.appspot.com/dl/gn/gn/%s/+/latest'
60    gn = 'gn' + ('.exe' if sys.platform == 'win32' else '')
61    if platform == 'mac-arm64': # For https://openradar.appspot.com/FB8914243
62        try: os.remove(os.path.join(dirname, gn))
63        except OSError: pass
64    download_and_unpack(url % platform, dirname, gn)
65    set_executable_bit(os.path.join(dirname, gn))
66
67
68if __name__ == '__main__':
69    sys.exit(main())
70