@@ -495,6 +495,14 @@ BIGTRACE_DEPS = [
495495 '6c3e8482f7b4e3b307bb42afbb85fd8771da86b8' , 'all' , 'all' , True )
496496]
497497
498+ # Dependencies to build Rust SDK.
499+ BUILD_DEPS_RUST = [
500+ Dependency (
501+ 'buildtools/rustup/rustup-init.sh' , 'https://sh.rustup.rs' ,
502+ '17247e4bcacf6027ec2e11c79a72c494c9af69ac8d1abcc1b271fa4375a106c2' ,
503+ 'all' , 'all' ),
504+ ]
505+
498506# Sysroots required to cross-compile Linux targets (linux-arm{,64}).
499507# These are taken from Chromium's build/linux/sysroot_scripts/sysroots.json.
500508BUILD_DEPS_LINUX_CROSS_SYSROOTS = [
@@ -513,7 +521,7 @@ BUILD_DEPS_LINUX_CROSS_SYSROOTS = [
513521ALL_DEPS = (
514522 BUILD_DEPS_HOST + BUILD_DEPS_BAZEL + BUILD_DEPS_ANDROID +
515523 BUILD_DEPS_LINUX_CROSS_SYSROOTS + TEST_DEPS_ANDROID +
516- EMULATOR_DEPS_ANDROID + UI_DEPS )
524+ EMULATOR_DEPS_ANDROID + UI_DEPS + BUILD_DEPS_RUST )
517525
518526ROOT_DIR = os .path .dirname (os .path .dirname (os .path .abspath (__file__ )))
519527UI_DIR = os .path .join (ROOT_DIR , 'ui' )
@@ -526,6 +534,11 @@ PYTHON_VENV_BIN_DIR = os.path.join(
526534PYTHON_STATUS_FILE = os .path .join (PYTHON_VENV_DIR , '.last_install' )
527535PYTHON_REQUIREMENTS = os .path .join (ROOT_DIR , 'python' , 'requirements.txt' )
528536TEST_DATA_SCRIPT = os .path .join (TOOLS_DIR , 'test_data' )
537+ RUST_TOOLCHAIN = os .environ .get ("RUST_TOOLCHAIN" , "nightly-2025-01-03" )
538+ RUSTUP_HOME = os .path .join (ROOT_DIR , 'buildtools/rustup' )
539+ RUSTUP_INIT_FILE = os .path .join (RUSTUP_HOME , 'rustup-init.sh' )
540+ CARGO_HOME = os .path .join (ROOT_DIR , '.cargo' )
541+ RUSTUP_FILE = os .path .join (CARGO_HOME , 'bin/rustup' )
529542
530543
531544def CheckCallRetry (* args , ** kwargs ):
@@ -693,6 +706,55 @@ def CheckNodeModules():
693706 return expected == actual
694707
695708
709+ def InstallRustToolchain (force_clean = False ):
710+ if force_clean :
711+ logging .info ('Clearing %s' , RUSTUP_HOME )
712+ subprocess .check_call (
713+ ['git' , 'clean' , '-qxffd' , RUSTUP_HOME , '--exclude=rustup-init.sh' ],
714+ cwd = ROOT_DIR )
715+ logging .info ('Clearing %s' , CARGO_HOME )
716+ subprocess .check_call (['git' , 'clean' , '-qxffd' , CARGO_HOME ], cwd = ROOT_DIR )
717+
718+ cmd = [
719+ 'sh' , RUSTUP_INIT_FILE , '-y' , f'--default-toolchain={ RUST_TOOLCHAIN } ' ,
720+ '--no-modify-path' , '--profile=minimal' , '--component=rustfmt,clippy'
721+ ]
722+ env = os .environ .copy ()
723+ env ['RUSTUP_HOME' ] = RUSTUP_HOME
724+ env ['CARGO_HOME' ] = CARGO_HOME
725+ logging .info (f'Installing rust toolchain using `{ " " .join (cmd )} `' )
726+ subprocess .check_call (cmd , cwd = ROOT_DIR , env = env )
727+
728+
729+ def CheckRustToolchain ():
730+ """Returns True if the toolchain is up-to-date.
731+
732+ Checks if Rust toolchains are up to date using `rustup check`
733+ and returns True if up to date, False otherwise.
734+ """
735+ if not os .path .exists (RUSTUP_FILE ):
736+ return False
737+
738+ # Run rustup check and capture its output and exit code.
739+ env = os .environ .copy ()
740+ env ['RUSTUP_HOME' ] = RUSTUP_HOME
741+ env ['CARGO_HOME' ] = CARGO_HOME
742+ result = subprocess .run ([RUSTUP_FILE , "check" ],
743+ capture_output = True ,
744+ text = True ,
745+ check = False )
746+ if result .returncode == 0 :
747+ if "update available" not in result .stdout .lower (
748+ ) and "update available" not in result .stderr .lower ():
749+ return True
750+ logging .info ("rustup check stdout:" )
751+ logging .info (result .stdout )
752+ logging .info ("rustup check stderr:" )
753+ logging .info (result .stderr )
754+ logging .info (f"rustup check exit code: { result .returncode } " )
755+ return False
756+
757+
696758def CheckPythonVenv ():
697759 """Returns True if the python venv is up-to-date."""
698760 if not os .path .exists (PYTHON_STATUS_FILE ):
@@ -799,6 +861,10 @@ def Main():
799861 default = GetArch (),
800862 choices = ['arm64' , 'x64' ],
801863 help = 'Override the autodetected build CPU architecture' )
864+ parser .add_argument (
865+ '--rust-toolchain' ,
866+ action = 'store_true' ,
867+ help = 'Rust toolchain to build Rust SDK' )
802868 args = parser .parse_args ()
803869 if args .verify :
804870 CheckHashes ()
@@ -830,8 +896,11 @@ def Main():
830896 # TODO(b/360084012) Change the arg name to bigtrace
831897 if args .grpc :
832898 deps += BIGTRACE_DEPS
899+ if args .rust_toolchain :
900+ deps += BUILD_DEPS_RUST
833901 deps_updated = False
834902 nodejs_updated = False
903+ rustup_updated = False
835904
836905 for old_dir in CLEANUP_OLD_DIRS :
837906 RmtreeIfExists (os .path .join (ROOT_DIR , old_dir ))
@@ -877,6 +946,8 @@ def Main():
877946 shutil .move (download_path , local_path )
878947 if 'nodejs' in dep .target_folder :
879948 nodejs_updated = True
949+ if 'rustup' in dep .target_folder :
950+ rustup_updated = True
880951
881952 assert (HashLocalFile (local_path ) == dep .checksum )
882953
@@ -935,6 +1006,12 @@ def Main():
9351006 elif venv_needs_update :
9361007 InstallPythonVenv ()
9371008
1009+ if args .rust_toolchain :
1010+ if args .check_only :
1011+ deps_updated |= not CheckRustToolchain ()
1012+ else :
1013+ InstallRustToolchain (force_clean = rustup_updated )
1014+
9381015 # Install the pre-push hook if the .git/hooks directory exists and it's a
9391016 # non check-only invocation. Not on windows (symlinks are not supported
9401017 # there).
0 commit comments