tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

install-sysroot.py (5993B)


      1 #!/usr/bin/env python3
      2 # Copyright 2013 The Chromium Authors
      3 # Use of this source code is governed by a BSD-style license that can be
      4 # found in the LICENSE file.
      5 
      6 """Install Debian sysroots for building chromium.
      7 """
      8 
      9 # The sysroot is needed to ensure that binaries that get built will run on
     10 # the oldest stable version of Debian that we currently support.
     11 # This script can be run manually but is more often run as part of gclient
     12 # hooks. When run from hooks this script is a no-op on non-linux platforms.
     13 
     14 # The sysroot image could be constructed from scratch based on the current state
     15 # of the Debian archive but for consistency we use a pre-built root image (we
     16 # don't want upstream changes to Debian to effect the chromium build until we
     17 # choose to pull them in). The images will normally need to be rebuilt every
     18 # time chrome's build dependencies are changed but should also be updated
     19 # periodically to include upstream security fixes from Debian.
     20 
     21 # This script looks at sysroots.json next to it to find the name of a .tar.xz
     22 # to download and the location to extract it to. The extracted sysroot could for
     23 # example be in build/linux/debian_bullseye_amd64-sysroot/.
     24 
     25 
     26 import glob
     27 import hashlib
     28 import json
     29 import optparse
     30 import os
     31 import shutil
     32 import subprocess
     33 import sys
     34 from urllib.request import urlopen
     35 
     36 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
     37 SRC_DIR = os.path.dirname(os.path.dirname(os.path.dirname(SCRIPT_DIR)))
     38 
     39 VALID_ARCHS = ("amd64", "i386", "armhf", "arm64", "mipsel", "mips64el",
     40               "ppc64el")
     41 
     42 ARCH_TRANSLATIONS = {
     43    "x64": "amd64",
     44    "x86": "i386",
     45    "arm": "armhf",
     46    "mips": "mipsel",
     47    "mips64": "mips64el",
     48    "ppc64le": "ppc64el",
     49 }
     50 
     51 DEFAULT_SYSROOTS_PATH = os.path.join(os.path.relpath(SCRIPT_DIR, SRC_DIR),
     52                                     "sysroots.json")
     53 DEFAULT_TARGET_PLATFORM = "bullseye"
     54 
     55 
     56 class Error(Exception):
     57    pass
     58 
     59 
     60 def GetSha256(filename):
     61    sha1 = hashlib.sha256()
     62    with open(filename, "rb") as f:
     63        while True:
     64            # Read in 1mb chunks, so it doesn't all have to be loaded into
     65            # memory.
     66            chunk = f.read(1024 * 1024)
     67            if not chunk:
     68                break
     69            sha1.update(chunk)
     70    return sha1.hexdigest()
     71 
     72 
     73 def main(args):
     74    parser = optparse.OptionParser("usage: %prog [OPTIONS]",
     75                                   description=__doc__)
     76    parser.add_option("--sysroots-json-path",
     77                      help="The location of sysroots.json file")
     78    parser.add_option("--arch",
     79                      help="Sysroot architecture: %s" % ", ".join(VALID_ARCHS))
     80    parser.add_option(
     81        "--all",
     82        action="store_true",
     83        help="Install all sysroot images (useful when updating the"
     84        " images)",
     85    )
     86    options, _ = parser.parse_args(args)
     87 
     88    if options.sysroots_json_path:
     89        sysroots_json_path = options.sysroots_json_path
     90    else:
     91        sysroots_json_path = DEFAULT_SYSROOTS_PATH
     92 
     93    if options.arch:
     94        InstallSysroot(
     95            sysroots_json_path,
     96            DEFAULT_TARGET_PLATFORM,
     97            ARCH_TRANSLATIONS.get(options.arch, options.arch),
     98        )
     99    elif options.all:
    100        for arch in VALID_ARCHS:
    101            InstallSysroot(sysroots_json_path, DEFAULT_TARGET_PLATFORM, arch)
    102    else:
    103        print("You much specify one of the options.")
    104        return 1
    105 
    106    return 0
    107 
    108 
    109 def GetSysrootDict(sysroots_json_path, target_platform, target_arch):
    110    if target_arch not in VALID_ARCHS:
    111        raise Error("Unknown architecture: %s" % target_arch)
    112 
    113    sysroots_file = os.path.join(SRC_DIR, sysroots_json_path)
    114    sysroots = json.load(open(sysroots_file))
    115    sysroot_key = "%s_%s" % (target_platform, target_arch)
    116    if sysroot_key not in sysroots:
    117        raise Error("No sysroot for: %s %s" % (target_platform, target_arch))
    118    return sysroots[sysroot_key]
    119 
    120 
    121 def InstallSysroot(sysroots_json_path, target_platform, target_arch):
    122    sysroot_dict = GetSysrootDict(sysroots_json_path, target_platform,
    123                                  target_arch)
    124    tarball_filename = sysroot_dict["Tarball"]
    125    tarball_sha256sum = sysroot_dict["Sha256Sum"]
    126    url_prefix = sysroot_dict["URL"]
    127    # TODO(thestig) Consider putting this elsewhere to avoid having to recreate
    128    # it on every build.
    129    linux_dir = os.path.dirname(SCRIPT_DIR)
    130    sysroot = os.path.join(linux_dir, sysroot_dict["SysrootDir"])
    131 
    132    url = "%s/%s" % (url_prefix, tarball_sha256sum)
    133 
    134    stamp = os.path.join(sysroot, ".stamp")
    135    # This file is created by first class GCS deps. If this file exists,
    136    # clear the entire directory and download with this script instead
    137    if os.path.exists(stamp) and not glob.glob(
    138            os.path.join(sysroot, ".*_is_first_class_gcs")):
    139        with open(stamp) as s:
    140            if s.read() == url:
    141                return
    142 
    143    print("Installing Debian %s %s root image: %s" %
    144          (target_platform, target_arch, sysroot))
    145    if os.path.isdir(sysroot):
    146        shutil.rmtree(sysroot)
    147    os.mkdir(sysroot)
    148    tarball = os.path.join(sysroot, tarball_filename)
    149    print("Downloading %s" % url)
    150    sys.stdout.flush()
    151    sys.stderr.flush()
    152    for _ in range(3):
    153        try:
    154            response = urlopen(url)
    155            with open(tarball, "wb") as f:
    156                f.write(response.read())
    157            break
    158        except Exception:  # Ignore exceptions.
    159            pass
    160    else:
    161        raise Error("Failed to download %s" % url)
    162    sha256sum = GetSha256(tarball)
    163    if sha256sum != tarball_sha256sum:
    164        raise Error("Tarball sha256sum is wrong."
    165                    "Expected %s, actual: %s" % (tarball_sha256sum, sha256sum))
    166    subprocess.check_call(["tar", "mxf", tarball, "-C", sysroot])
    167    os.remove(tarball)
    168 
    169    with open(stamp, "w") as s:
    170        s.write(url)
    171 
    172 
    173 if __name__ == "__main__":
    174    try:
    175        sys.exit(main(sys.argv[1:]))
    176    except Error as e:
    177        sys.stderr.write(str(e) + "\n")
    178        sys.exit(1)