| #!/usr/bin/env python3 |
| # Copyright 2023 The Chromium Authors |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| """Update in-tree checkout of Rust toolchain |
| |
| Minimal Skia adapation of [1] to fetch a Rust revision manually |
| specified in MANUAL_REVISION below. Frequently roll this to latest |
| version available in [2]. |
| |
| [1] https://source.chromium.org/chromium/chromium/src/+/main:tools/rust/update_rust.py |
| [2] https://commondatastorage.googleapis.com/chromium-browser-clang/index.html?path=Linux_x64/rust-toolchain- |
| |
| """ |
| |
| import argparse |
| import os |
| import re |
| import shutil |
| import sys |
| import tempfile |
| import urllib |
| |
| from pathlib import Path |
| |
| # Chromium's Rust builds (for Linux) that worked are found at: |
| # https://commondatastorage.googleapis.com/chromium-browser-clang/index.html?path=Linux_x64/rust-toolchain- |
| # The latest builds are prefixed with a date, such as `20230101-1`. |
| # To update, roll this to versions that Chromium's tools/rust/build-rust.py has produced and which are found from the CDS url. |
| MANUAL_REVISION = ( |
| "ac4379fea9e83465d814bb05005689f49bd2141e-1-llvmorg-17-init-3874-g93a2fecc-1" |
| ) |
| |
| THIS_DIR = os.path.abspath(os.path.dirname(__file__)) |
| SKIA_DIR = os.path.abspath(os.path.join(THIS_DIR, "..")) |
| THIRD_PARTY_DIR = os.path.join(SKIA_DIR, "third_party") |
| RUST_TOOLCHAIN_OUT_DIR = os.path.join(THIRD_PARTY_DIR, "rust-toolchain") |
| VERSION_STAMP_PATH = os.path.join(RUST_TOOLCHAIN_OUT_DIR, "VERSION") |
| |
| |
| def GetDownloadPackageVersion(): |
| # TODO(https://crbug.com/14191): This is hardcoded in Skia right |
| # now, as Skia does not rebuild rust on its own and can't directly |
| # access the most recent version that's been built for |
| # Chromium. Could the Chromium side-build publish something like a |
| # symbolic link to last-known-good? |
| return MANUAL_REVISION |
| |
| |
| # Get the version of the toolchain package we already have. |
| def GetStampVersion(): |
| if os.path.exists(RUST_TOOLCHAIN_OUT_DIR): |
| with open(VERSION_STAMP_PATH) as version_file: |
| existing_stamp = version_file.readline().rstrip() |
| version_re = re.compile(r"rustc [0-9.]+ [0-9a-f]+ \((.+?) chromium\)") |
| match = version_re.fullmatch(existing_stamp) |
| if match is None: |
| return None |
| return match.group(1) |
| |
| return None |
| |
| |
| def main(): |
| parser = argparse.ArgumentParser(description="Update Rust package") |
| parser.add_argument( |
| "--print-package-version", |
| action="store_true", |
| help="Print Rust package version (including both the " |
| "Rust and Clang revisions) and quit.", |
| ) |
| args = parser.parse_args() |
| |
| if args.print_package_version: |
| print(GetDownloadPackageVersion()) |
| return 0 |
| |
| from clang_update import DownloadAndUnpack, GetDefaultHostOs, GetPlatformUrlPrefix |
| |
| # Exit early if the existing package is up-to-date. Note that we cannot |
| # simply call DownloadAndUnpack() every time: aside from unnecessarily |
| # downloading the toolchain if it hasn't changed, it also leads to multiple |
| # versions of the same rustlibs. build/rust/std/find_std_rlibs.py chokes in |
| # this case. |
| if os.path.exists(RUST_TOOLCHAIN_OUT_DIR): |
| if GetDownloadPackageVersion() == GetStampVersion(): |
| return 0 |
| |
| if os.path.exists(RUST_TOOLCHAIN_OUT_DIR): |
| shutil.rmtree(RUST_TOOLCHAIN_OUT_DIR) |
| |
| try: |
| host_os = GetDefaultHostOs() |
| # TODO(https://crbug.com/skia/14190): Enable this on additional |
| # platforms. |
| if not "linux" in host_os: |
| print( |
| "Unsupported platform, Rust support only available on Linux " |
| "at the moment, see https://crbug.com/skia/14190" |
| ) |
| return 1 |
| platform_prefix = GetPlatformUrlPrefix(host_os) |
| version = GetDownloadPackageVersion() |
| url = f"{platform_prefix}rust-toolchain-{version}.tgz" |
| DownloadAndUnpack(url, THIRD_PARTY_DIR) |
| except urllib.error.HTTPError as e: |
| # Fail softly for now. This can happen if a Rust package was not |
| # produced, e.g. if the Rust build failed upon a Clang update, or if a |
| # Rust roll and a Clang roll raced against each other. |
| # |
| # TODO(https://crbug.com/1245714): Reconsider how to handle this. |
| print(f"warning: could not download Rust package") |
| |
| # Ensure the newly extracted package has the correct version. |
| assert GetDownloadPackageVersion() == GetStampVersion() |
| |
| |
| if __name__ == "__main__": |
| sys.exit(main()) |