#!/usr/bin/env fuchsia-vendored-python
# Copyright 2022 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Wraps a Rust compile command for remote execution (reclient, RBE).

Given a Rust compile command, this script
1) identifies all inputs needed to execute the command hermetically (remotely).
2) identifies all outputs to be retrieved from remote execution.
3) composes a `rewrapper` (reclient) command to request remote execution.
   This includes downloading remotely produced artifacts.
4) forwards stdout/stderr back to the local environment

This script was ported over from build/rbe/rustc-remote-wrapper.sh.

For full usage, see `rustc_remote_wrapper.py -h`.
"""

import argparse
import glob
import os
import subprocess
import stat
import sys

import cl_utils
import depfile
import fuchsia
import linker
import rustc
import remote_action

from pathlib import Path
from typing import Any, Iterable, Optional, Sequence

_SCRIPT_BASENAME = Path(__file__).name

# standard '755' executable permissions
_EXEC_PERMS = (
    stat.S_IRWXU | (stat.S_IRGRP | stat.S_IXGRP) | (stat.S_IROTH | stat.S_IXOTH)
)


def msg(text: str):
    print(f"[{_SCRIPT_BASENAME}] {text}")


# string.removeprefix() only appeared in python 3.9
def remove_prefix(text: str, prefix: str) -> str:
    if text.startswith(prefix):
        return text[len(prefix) :]
    return text


# This is needed in some places to workaround b/203540556 (reclient).
def remove_dot_slash_prefix(text: str) -> str:
    return remove_prefix(text, "./")


# string.removesuffix() only appeared in python 3.9
def remove_suffix(text: str, suffix: str) -> str:
    if text.endswith(suffix):
        return text[: -len(suffix)]
    return text


# Defined for convenient mocking.
def _readlines_from_file(path: Path) -> Sequence[str]:
    return path.read_text().splitlines(keepends=True)


# Defined for convenient mocking.
def _make_local_depfile(command: Sequence[str]) -> int:
    return subprocess.call(command)


# Defined for convenient mocking.
def _tool_is_executable(tool: Path) -> bool:
    return os.access(tool, os.X_OK)


# Defined for convenient mocking.
def _libcxx_isfile(libcxx: Path) -> bool:
    return libcxx.is_file()


# Defined for convenient mocking.
def _env_file_exists(path: Path) -> bool:
    return path.exists()


def _flatten_comma_list_to_paths(items: Iterable[str]) -> Iterable[Path]:
    for item in cl_utils.flatten_comma_list(items):
        yield Path(item)


def _main_arg_parser() -> argparse.ArgumentParser:
    """Construct the argument parser, called by main()."""
    parser = argparse.ArgumentParser(
        description="Prepares a Rust compile command for remote execution.",
        argument_default=[],
    )
    remote_action.inherit_main_arg_parser_flags(parser)

    # There could be multiple variants of the standard C++ library to choose
    # from.  Use the one that corresponds to the compiler options.
    parser.add_argument(
        "--cxx-stdlibdir",
        type=Path,
        default=None,
        help="Where to find libc++ (from clang)",
    )

    return parser


_MAIN_ARG_PARSER = _main_arg_parser()


def relativize_paths(paths: Iterable[Path], start: Path) -> Iterable[Path]:
    for p in paths:
        if p.is_absolute():
            yield cl_utils.relpath(p, start=start)
        else:
            yield p  # Paths are already normalized upon construction


def accompany_rlib_with_so(deps: Iterable[Path]) -> Iterable[Path]:
    """Expand list to include .so files.

    Some Rust libraries come with both .rlib and .so (like libstd), however,
    the depfile generator fails to list the .so file in some cases,
    which causes the build to silently fallback to static linking when
    dynamic linking is requested and intended.  This can result in a mismatch
    between local and remote building.
    See https://github.com/rust-lang/rust/issues/90106
    Workaround (https://fxbug.dev/42167956): check for existence of .so and include it.

    Yields:
      original sequence, plus potentially additional .so libs.
    """
    for dep in deps:
        yield dep
        if dep.suffix == ".rlib":
            so_file = dep.with_suffix(".so")  # replaces .rlib with .so
            if so_file.is_file():
                yield so_file


def expand_deps_for_rlib_compile(paths: Iterable[Path]) -> Iterable[Path]:
    """Expand a list of rmeta deps to be suitable for full (rlib) compilation.

    Depending on the rustc options used for scanning for dependencies,
    the deps may contain list the .rmeta metadata file for some
    entries (because only metadata is needed for fast operations like
    dep-scanning).  However, for the purposes of compiling a real .rlib
    (or other rust artifact) we need to interpret this as requiring the
    corresponding .rlib.
    The implied .rlib need not necessarily exist on disk with real
    contents; it is permitted to be a download stub from an earlier
    remote build.

    Yields:
      possibly modified deps.
    """
    for path in paths:
        yield path
        if path.name.endswith(".rmeta"):
            f = path.with_suffix(".rlib")
            if f.exists():  # ok to exist as download stub
                yield f
                continue

            # .so proc macros already appear as deps in the depfile
            # so there is no need to repeat them here.
            pass


class RemoteInputProcessingError(RuntimeError):
    def __init__(self, message: str):
        super().__init__(message)


def _filter_local_command(args: Iterable[str]) -> Sequence[str]:
    return list(cl_utils.strip_option_prefix(args, "--local-only"))


class RustRemoteAction(object):
    def __init__(
        self,
        argv: Sequence[str],
        exec_root: Optional[Path] = None,
        working_dir: Optional[Path] = None,
        host_platform: str = None,
        auto_reproxy: bool = True,  # Ok to disable during unit-tests
    ):
        self._working_dir = (working_dir or Path(os.curdir)).absolute()
        self._exec_root = (exec_root or remote_action.PROJECT_ROOT).absolute()
        self._host_platform = host_platform or fuchsia.HOST_PREBUILT_PLATFORM

        # Propagate --remote-flag=... options to the remote prefix,
        # as if they appeared before '--'.
        # Forwarded rewrapper options with values must be written as '--flag=value',
        # not '--flag value' because argparse doesn't know what unhandled flags
        # expect values.
        main_argv, filtered_command = remote_action.forward_remote_flags(argv)

        # Forward all unknown flags to rewrapper
        # --help here will result in early exit()
        (
            self._main_args,
            self._main_remote_options,
        ) = _MAIN_ARG_PARSER.parse_known_args(main_argv)

        # Re-launch with reproxy if needed.
        if auto_reproxy:
            remote_action.auto_relaunch_with_reproxy(
                script=Path(__file__), argv=argv, args=self._main_args
            )

        if not filtered_command:  # there is no command, bail out early
            return

        self._rust_action = rustc.RustAction(
            command=filtered_command,
            working_dir=self.working_dir,
        )

        # TODO: check for missing required flags, like --target

        self._local_only = self._main_args.local or self._remote_disqualified()

        self._cleanup_files: Sequence[Path] = []
        self._prepare_status: int = None  # 0 means success, like an exit code
        self._remote_action = None  # will be set by prepare() step

    @property
    def _c_sysroot_is_outside_exec_root(self) -> bool:
        c_sysroot_dir = self.c_sysroot
        if not c_sysroot_dir:
            return False  # not applicable

        if not c_sysroot_dir.is_absolute():
            # C sysroot is relative to the working directory
            return False

        # Check all absolute path parents.
        return self.exec_root not in c_sysroot_dir.parents

    def _remote_disqualified(self):
        """Detects when the action cannot run remotely for various reasons."""
        # If the C sysroot is outside of exec_root, (e.g. an absolute path
        # like /Library/Developer/... for Mac OS SDKs) then the command
        # will only work locally.
        if self.needs_linker:
            if self._c_sysroot_is_outside_exec_root:
                self.vmsg(
                    f"Forcing local execution because C sysroot ({self.c_sysroot}) is outside of exec_root ({self.exec_root})."
                )
                return True

        # TODO: procedural macros need to target the host AND the remote
        # platform to be usable both locally and remotely.
        # For now, only build with procedural macros locally.
        if any(
            path.suffix == ".dylib"
            for path in self._rust_action.externs.values()
        ):
            self.vmsg(
                f"Forcing local execution because one of the externs points to a .dylib, which does not work in the remote environment."
            )
            return True

        return False

    @property
    def verbose(self) -> bool:
        return self._main_args.verbose

    def vmsg(self, text: str):
        if self.verbose:
            msg(text)

    @property
    def dry_run(self) -> bool:
        return self._main_args.dry_run

    @property
    def check_determinism(self) -> bool:
        return self._main_args.check_determinism

    @property
    def determinism_attempts(self) -> int:
        return self._main_args.determinism_attempts

    @property
    def miscomparison_export_dir(self) -> Optional[Path]:
        if self._main_args.miscomparison_export_dir:
            return self.working_dir / self._main_args.miscomparison_export_dir
        return None

    @property
    def clang_cxx_stdlibdir(self) -> Optional[Path]:
        return self._main_args.cxx_stdlibdir

    @property
    def local_only(self) -> bool:
        """If the conditions are not right for remote execution, disable,
        regardless of configuration.
        """
        return self._local_only

    @property
    def label(self) -> str:
        return self._main_args.label

    def vmsg(self, text: str):
        if self.verbose:
            msg(text)

    def value_verbose(self, desc: str, value: str) -> str:
        """In verbose mode, print and forward value."""
        self.vmsg(f"{desc}: {value}")
        return value

    def yield_verbose(self, desc: str, items: Iterable[Any]) -> Iterable[Any]:
        """In verbose mode, print and forward items.

        Args:
          desc: text description of what is being printed.
          items: stream of any type of object that is str-able.

        Yields:
          items, unchanged
        """
        if self.verbose:
            msg(f"{desc}: {{")
            for item in items:
                print(f"  {item}")  # one item per line
                yield item
            print(f"}}  # {desc}")
        else:
            yield from items

    @property
    def working_dir(self) -> Path:
        return self._working_dir

    @property
    def exec_root(self) -> Path:
        return self._exec_root

    @property
    def label(self) -> Optional[str]:
        return self._main_args.label

    @property
    def host_platform(self) -> str:
        return self._host_platform

    @property
    def exec_root_rel(self) -> Path:
        # relpath can handle cases that Path.relative_to() cannot.
        return cl_utils.relpath(self.exec_root, start=self.working_dir)

    @property
    def build_subdir(self) -> Path:  # relative
        """This is the relative path from the exec_root to the current working dir."""
        return self.working_dir.relative_to(self.exec_root)

    @property
    def crate_type(self) -> rustc.CrateType:
        return self._rust_action.crate_type

    @property
    def needs_linker(self) -> bool:
        return self._rust_action.needs_linker

    @property
    def target(self) -> Optional[str]:
        return self._rust_action.target

    @property
    def rust_sysroot(self) -> Optional[Path]:
        return self._rust_action.rust_sysroot

    @property
    def c_sysroot(self) -> Optional[Path]:
        return self._rust_action.c_sysroot

    @property
    def linker(self) -> Optional[Path]:
        return self._rust_action.linker

    @property
    def local_clang_toolchain_dir(self) -> Path:
        """Infer the clang toolchain dir based on the linker location.

        Returns:
          Path to a toolchain dir, relative to the working dir.
        """
        linker = self.linker  # a relative path
        if not linker:
            return self.exec_root_rel / fuchsia.REMOTE_CLANG_SUBDIR
        # We want TOOLDIR from a path like TOOLDIR/bin/TOOL.
        # This follows a typical clang install structure.
        return linker.parent.parent

    @property
    def remote_clang_toolchain_dir(self) -> Path:  # relative
        return fuchsia.remote_executable(self.local_clang_toolchain_dir)

    @property
    def depfile(self) -> Optional[Path]:
        return self._rust_action.depfile

    @property
    def primary_output(self) -> Path:
        return self._rust_action.output_file

    @property
    def host_compiler(self) -> Path:
        return self._rust_action.compiler

    @property
    def remote_compiler(self) -> Path:
        return fuchsia.remote_executable(self.host_compiler)

    @property
    def host_matches_remote(self) -> bool:
        return self.remote_compiler == self.host_compiler

    @property
    def original_command(self) -> Sequence[str]:
        return self._rust_action.original_command

    def _replace_with_remote_compiler(self, tok) -> Optional[str]:
        if tok == str(self.host_compiler):
            return str(self.remote_compiler)

    @staticmethod
    def _replace_with_remote_linker(tok) -> Optional[str]:
        """Replace the host platform linker with the remote platform one."""
        return cl_utils.match_prefix_transform_suffix(
            tok, "-Clinker=", lambda x: str(fuchsia.remote_executable(Path(x)))
        )

    @staticmethod
    def _normalize_libcxx(tok) -> Optional[str]:
        # A path like ".../bin/../lib/libc++a" needs to be normalized
        # so that the remote linker does not fail when looking for a
        # non-existent "bin" part of the path.
        prefix = "-Clink-arg="
        if tok.startswith(prefix) and tok.endswith(".a") and ".." in tok:
            right = tok[len(prefix) :]
            # We do not want the Path.resolve() behavior of following
            # symlinks and checking for existence; we truly want simple
            # os.path.normpath() behavior.
            normpath = os.path.normpath(right)
            return prefix + normpath

    @property
    def local_depfile(self) -> Path:
        return Path(str(self.depfile) + ".nolink")

    @property
    def dep_only_command(self) -> Sequence[str]:
        return cl_utils.auto_env_prefix_command(
            _filter_local_command(
                self._rust_action.dep_only_command(self.local_depfile)
            )
        )

    def remote_compile_command(self) -> Iterable[str]:
        """Transforms a local command into the remotely executed command.

        Note: that response files are preserved, so tokens inside response files
        cannot be modified.
        """
        for tok in self.original_command:
            # Apply the first matching transform on each token.
            replacement = self._replace_with_remote_compiler(tok)
            if replacement is not None:
                yield replacement
                continue

            replacement = self._replace_with_remote_linker(tok)
            if replacement is not None:
                yield replacement
                continue

            replacement = self._normalize_libcxx(tok)
            if replacement is not None:
                yield replacement
                continue

            # When using -fuse-ld, also hint at the full path to the
            # linker tool that is expected, without having to prepend
            # PATH in the remote environment.
            # This is only needed for remote cross-compilation.
            if (
                tok.startswith("-Clink-arg=-fuse-ld=")
                and not self.host_matches_remote
            ):
                yield tok
                yield f"-Clink-arg=--ld-path={self.remote_ld_path}"
                continue

            # else
            yield tok

        # TODO(https://fxbug.dev/42057067): relocate rust sysroot to
        # be indepedent of host-platform to make remote commands
        # match for better caching.
        # The rust sysroot is home to the standard libraries for
        # all target platforms.
        # Fuchsia currently uses the default sysroot location which is
        # based on the *host* compiler path, but the remote compiler's
        # default sysroot will be different.
        # Inform the remote compiler to use the location of the sysroot
        # of the *host* compiler.
        fuchsia_use_host_rust_sysroot = self._rust_action.default_rust_sysroot()
        yield f"--sysroot={fuchsia_use_host_rust_sysroot}"

    def _cleanup(self):
        for f in self._cleanup_files:
            f.unlink(missing_ok=True)  # does remove or rmdir

    def _local_depfile_inputs(self) -> Iterable[Path]:
        # Generate a local depfile for the purposes of discovering
        # all transitive inputs.
        self._cleanup_files.append(self.local_depfile)

        dep_only_command = self.dep_only_command
        cmd_str = cl_utils.command_quoted_str(dep_only_command)
        self.vmsg(f"scan-deps-only command: {cmd_str}")
        dep_status = _make_local_depfile(dep_only_command)
        if dep_status != 0:
            self._prepare_status = dep_status
            if self.verbose:
                # This is really a lot of information, which is only interesting
                # in limited circumstances. So we don't print it unless requested.
                raise RemoteInputProcessingError(
                    f"Error: Local generation of depfile failed (exit={dep_status}): {cmd_str}"
                )
            else:
                raise RemoteInputProcessingError(
                    f"Error: Local generation of depfile failed (exit={dep_status}), use --verbose to see the command line."
                )

        # There is a phony dep for each input that is needed.
        deps = list(
            depfile.parse_lines(_readlines_from_file(self.local_depfile))
        )
        target_paths = [dep.target_paths for dep in deps if dep.is_phony]
        remote_depfile_inputs = [
            target for paths in target_paths for target in paths
        ]

        # Expand some .rmeta deps for .rlib compilation.
        expanded_remote_inputs = list(
            expand_deps_for_rlib_compile(remote_depfile_inputs)
        )

        # TODO: if needed, transform the rust std lib paths, depending on
        #   Fuchsia directory layout of Rust prebuilt libs.
        #   See remap_remote_rust_lib() in rustc-remote-wrapper.sh
        #   for one possible implementation.
        yield from self.yield_verbose(
            "depfile inputs",
            relativize_paths(
                accompany_rlib_with_so(expanded_remote_inputs), self.working_dir
            ),
        )

    def _remote_compiler_inputs(self) -> Iterable[Path]:
        # remote compiler is an input
        remote_compiler = self.remote_compiler
        if not _tool_is_executable(remote_compiler):
            raise RemoteInputProcessingError(
                f"Remote compilation requires {remote_compiler} to be available for uploading, but it is missing."
            )
        yield self.value_verbose("remote compiler", remote_compiler)
        yield from self._remote_rustc_shlibs()

    def _remote_rustc_shlibs(self) -> Iterable[Path]:
        """Find remote compiler shared libraries.

        Yields:
          shared library paths relative to current working dir.
        """
        if self.host_platform == fuchsia.REMOTE_PLATFORM:
            # remote and host execution environments match
            yield from self.yield_verbose(
                "remote compiler shlibs (detected)",
                relativize_paths(
                    remote_action.host_tool_nonsystem_shlibs(
                        self.remote_compiler
                    ),
                    self.working_dir,
                ),
            )
        else:
            yield from self._assumed_remote_rustc_shlibs()

    def _assumed_remote_rustc_shlibs(self) -> Iterable[Path]:
        # KLUDGE: the host's binutils may not be able to analyze the remote
        # executable (ELF), so hardcode what we think the shlibs are.
        yield from self.yield_verbose(
            "remote compiler shlibs (guessed)",
            fuchsia.remote_rustc_shlibs(self.exec_root_rel),
        )

    def _rust_stdlib_libunwind_inputs(self) -> Iterable[Path]:
        # The majority of stdlibs already appear in dep-info and are uploaded
        # as needed.  However, libunwind.a is not listed, but is directly
        # needed by code emitted by rustc.  Listing this here works around a
        # missing upload issue, and adheres to the guidance of listing files
        # instead of whole directories.
        if not self.target:
            return
        libunwind_a = (
            self.rust_sysroot
            / fuchsia.rust_stdlib_subdir(  # relative to self.working_dir
                target_triple=self.target
            )
            / "libunwind.a"
        )
        if libunwind_a.exists():
            yield self.value_verbose("libunwind", libunwind_a)

    def _inputs_from_env(self) -> Iterable[Path]:
        """Scan command environment variables for references to inputs files.

        If a variable value looks like a path and it points to something
        that exists, assume it is needed for remote execution.
        """
        for e in self._rust_action.env:
            key, sep, value = e.partition("=")
            if sep == "=":
                try:
                    p = Path(value)
                    if _env_file_exists(p):
                        yield cl_utils.relpath(p, start=self.working_dir)
                except ValueError:  # value is not a Path, ignore it
                    pass

    def _remote_inputs(self) -> Iterable[Path]:
        """Remote inputs are relative to current working dir."""
        yield self.value_verbose(
            "top source", self._rust_action.direct_sources[0]
        )

        # Pass along response files without altering the original command.
        yield from self._rust_action.response_files

        yield from self._local_depfile_inputs()

        yield from self._remote_compiler_inputs()

        yield from self._rust_stdlib_libunwind_inputs()

        # Indirect dependencies (libraries)
        yield from self.yield_verbose(
            "extern libs", self._rust_action.extern_paths()
        )

        # Prefer to have the build system's command specify additional
        # --remote-inputs instead of trying to infer them.
        # yield from self.yield_verbose('env var files', self._inputs_from_env())

        # Link arguments like static libs are checked for existence
        # but not necessarily used until linking a binary.
        # This is why we need to includes link_arg_files unconditionally,
        # whereas the linker tools themselves can be dropped until linking binaries.
        yield from self.yield_verbose(
            "link arg files", self._rust_action.link_arg_files
        )

        if self.needs_linker:
            yield from self._remote_linker_inputs()

        yield from self.yield_verbose(
            "forwarded inputs",
            _flatten_comma_list_to_paths(self._main_args.inputs),
        )

    def _remote_output_files(self) -> Iterable[Path]:
        """Remote output files are relative to current working dir."""
        yield self.value_verbose("main output", self.primary_output)

        depfile = self.depfile
        if depfile:
            yield self.value_verbose("depfile", depfile)

        yield from self.yield_verbose(
            "extra compiler outputs", self._rust_action.extra_output_files()
        )

        yield from self.yield_verbose(
            "forwarded output files",
            _flatten_comma_list_to_paths(self._main_args.output_files),
        )

    def _remote_output_dirs(self) -> Iterable[Path]:
        yield from self.yield_verbose(
            "forwarded output dirs",
            _flatten_comma_list_to_paths(self._main_args.output_directories),
        )

    @property
    def remote_options(self) -> Sequence[str]:
        """rewrapper remote execution options."""
        fixed_remote_options = [
            # type=tool says we are providing a custom tool (Rust compiler), and
            #   thus, own the logic for providing explicit inputs.
            # shallow=true works around an issue where racing mode downloads
            #   incorrectly
            # toolname=rustc just helps classify the remote action type
            "--labels=type=tool,shallow=true,toolname=rustc",
            # --canonicalize_working_dir: coerce the output dir to a constant.
            #   This requires that the command be insensitive to output dir, and
            #   that its outputs do not leak the remote output dir.
            #   Ensuring that the results reproduce consistently across different
            #   build directories helps with caching.
            "--canonicalize_working_dir=true",
        ]

        # _main_remote_options should be allowed to override the
        # fixed_remote_options
        return fixed_remote_options + self._main_remote_options

    def prepare(self) -> int:
        """Setup the remote action, but do not execute it.

        Returns:
          exit code, 0 for success
        """
        # cache the preparation
        if self._prepare_status is not None:
            return self._prepare_status

        # inputs and outputs are relative to current working dir
        try:
            remote_inputs = list(self._remote_inputs())
        except RemoteInputProcessingError as e:
            msg(e)
            return 1

        remote_output_files = list(self._remote_output_files())
        remote_output_dirs = list(self._remote_output_dirs())

        # Interpret --download_outputs=false as a request to avoid
        # downloading only the primary rustc output (often the largest
        # artifact).  In other words, always download *all* other outputs,
        # including the depfile and emitted llvm-ir (if applicable).
        # The depfile *must* be downloaded because it is consumed by ninja.

        translated_remote_options = []
        for opt in self.remote_options:
            if opt == "--download_outputs=false":
                translated_remote_options.append(
                    f"--download_regex=-{self.primary_output}$"
                )
            else:
                translated_remote_options.append(opt)

        self._remote_action = remote_action.remote_action_from_args(
            main_args=self._main_args,
            remote_options=translated_remote_options,
            command=list(self.remote_compile_command()),
            inputs=remote_inputs,
            output_files=remote_output_files,
            output_dirs=remote_output_dirs,
            working_dir=self.working_dir,
            exec_root=self.exec_root,
            post_remote_run_success_action=self._post_remote_success_action,
        )
        self._prepare_status = 0  # exit code success
        return self._prepare_status

    @property
    def remote_action(self) -> remote_action.RemoteAction:
        return self._remote_action

    @property
    def remote_linker(self) -> Optional[Path]:
        if not self.linker:
            return None
        return fuchsia.remote_executable(self.linker)

    @property
    def target_linker_prefix(self) -> Optional[str]:
        if not self.target:
            return None
        if "darwin" in self.target:
            return "ld64"
        return "ld"  # most cases

    @property
    def remote_ld_path(self) -> Optional[Path]:
        ld = self._rust_action.use_ld  # e.g. "lld"
        if not ld:
            return None
        prefix = self.target_linker_prefix
        if not prefix:
            return None
        return self.remote_linker.parent / f"{prefix}.{ld}"

    def _remote_linker_executables(self) -> Iterable[Path]:
        if self.linker:
            remote_linker = self.remote_linker
            yield self.value_verbose("remote linker", remote_linker)

            # ld.lld -> lld, but the symlink is required for the clang
            # linker driver to be able to use lld.
            # Nowadays, lld -> llvm.
            # ld.LINKER is expected to be in the remote environment PATH.
            # See ToolChain::GetLinkerPath() in llvm-project:clang/lib/Driver/ToolChain.cpp
            ld = self._rust_action.use_ld  # e.g. "lld"
            if ld:
                yield self.value_verbose(
                    "remote clang -fuse-ld", self.remote_ld_path
                )

    def _remote_libcxx(self, clang_lib_triple: str) -> Iterable[Path]:
        if self.clang_cxx_stdlibdir:  # override, selecting for variant
            libcxx_remote = self.clang_cxx_stdlibdir / "libc++.a"
        else:
            libcxx_remote = fuchsia.clang_libcxx_static(
                self.remote_clang_toolchain_dir, clang_lib_triple
            )
        if _libcxx_isfile(libcxx_remote):
            yield self.value_verbose("remote libc++", libcxx_remote)

    def _remote_clang_runtime_libs(
        self, clang_lib_triple: str
    ) -> Iterable[Path]:
        # clang runtime lib dir
        rt_libdir_remote = list(
            fuchsia.clang_runtime_libdirs(
                self.remote_clang_toolchain_dir, clang_lib_triple
            )
        )
        # if none found, that's ok.
        if len(rt_libdir_remote) == 1:
            yield self.value_verbose(
                "remote runtime libdir", rt_libdir_remote[0]
            )
        if len(rt_libdir_remote) > 1:
            raise RemoteInputProcessingError(
                f"Found more than one clang runtime lib dir (don't know which one to use): {rt_libdir_remote}"
            )

    def _c_sysroot_files(self) -> Iterable[Path]:
        # sysroot files
        if not self.target:
            return
        c_sysroot_dir = self.c_sysroot
        if not c_sysroot_dir:
            return
        # if sysroot points outside of exec_root, stop
        if self._c_sysroot_is_outside_exec_root:
            return
        sysroot_triple = fuchsia.rustc_target_to_sysroot_triple(self.target)
        if c_sysroot_dir:
            # Some sysroot files are linker scripts to be expanded.
            if sysroot_triple:
                search_paths = [
                    c_sysroot_dir / "usr/lib" / sysroot_triple,
                    c_sysroot_dir / "lib" / sysroot_triple,
                ]
            else:
                search_paths = [c_sysroot_dir / "lib"]

            link = linker.LinkerInvocation(
                working_dir_abs=self.working_dir, search_paths=search_paths
            )

            lld = self.host_compiler.parent / "ld.lld"  # co-located with clang

            def linker_script_expander(paths: Sequence[Path]) -> Iterable[Path]:
                if lld.exists():
                    yield from link.expand_using_lld(lld=lld, inputs=paths)
                else:
                    for path in paths:
                        yield from link.expand_possible_linker_script(path)

            yield from self.yield_verbose(
                "C sysroot files",
                fuchsia.c_sysroot_files(
                    sysroot_dir=c_sysroot_dir,
                    sysroot_triple=sysroot_triple,
                    with_libgcc=self._rust_action.want_sysroot_libgcc,
                    linker_script_expander=linker_script_expander,
                ),
            )

    def _remote_linker_inputs(self) -> Iterable[Path]:
        if self.linker:
            yield from self._remote_linker_executables()

            if self.target:
                clang_lib_triple = fuchsia.rustc_target_to_clang_target(
                    self.target
                )
                yield from self._remote_libcxx(clang_lib_triple)
                yield from self._remote_clang_runtime_libs(clang_lib_triple)

        # --crate-type cdylib needs rust-lld (hard-coding this is a hack)
        # This will always be linux-x64, even when cross-compiling, because
        # that is the only RBE remote backend option available.
        if self.crate_type == rustc.CrateType.CDYLIB:
            yield self.value_verbose(
                "remote rust-lld",
                fuchsia.remote_rustc_to_rust_lld_path(self.remote_compiler),
            )

        yield from self._c_sysroot_files()

    def _depfile_exists(self) -> bool:
        # Defined for easy mocking.
        return self.depfile and self.depfile.exists()

    def _post_remote_success_action(self) -> int:
        if self._depfile_exists():
            self._rewrite_remote_or_local_depfile()

        if (
            self.remote_action.skipping_some_download
            and self._rust_action.main_output_is_executable
        ):
            # TODO(b/285030257): This is a workaround to a problem where
            # download stubs need the appropriate execution permissions
            # to be set, so that remote execution inputs get the same
            # permissions.  This is important for tools that mirror execution
            # bits from inputs to outputs, like llvm-objcopy.
            # Once re-client presents permission information in the
            # --action_log (reproxy remote_metadata), this workaround can
            # be replaced with a more generalized solution.
            if remote_action.is_download_stub_file(self.primary_output):
                self.primary_output.chmod(_EXEC_PERMS)
        return 0

    def _rewrite_remote_or_local_depfile(self):
        """Rewrite depfile without working dir absolute paths.

        TEMPORARY WORKAROUND until upstream fix lands:
          https://github.com/pest-parser/pest/pull/522
        Rewrite the depfile if it contains any absolute paths from the remote
        build; paths should be relative to the root_build_dir.

        Assume that the output dir is two levels down from the exec_root.

        When using the `canonicalize_working_dir` rewrapper option,
        the output directory is coerced to a predictable 'set_by_reclient' constant.
        See https://source.corp.google.com/foundry-x-re-client/internal/pkg/reproxy/action.go;l=131
        It is still possible for a tool to leak absolute paths, which could
        expose that constant in returned artifacts.
        We forgive this for depfiles, but other artifacts should be verified
        separately.
        """
        # It is possible for this to run after local execution with
        # exec_strategy=local,racing,remote_local_fallback, so the logic
        # herein should accommodate both possibilities.
        # In the future, it might be possible to determine whether the local
        # or remote result was used from self.action_log.
        self.vmsg(f"Rewriting the (remote or local) depfile {self.depfile}")
        remote_action.rewrite_depfile(
            dep_file=self.working_dir / self.depfile,  # in-place
            transform=self.remote_action._relativize_remote_or_local_deps,
        )

    def run_remote(self) -> int:
        prepare_status = self.prepare()
        if prepare_status != 0:
            return prepare_status

        try:
            return self.remote_action.run_with_main_args(self._main_args)

        finally:
            self._cleanup()

    def run_local(self) -> int:
        # Even if this is running locally, some of intermediate inputs
        # have have come from remote actions that opted not to
        # download their outputs (and left only download stubs).
        # To be safe, verify the inputs and download as needed.

        prepare_status = self.prepare()
        if prepare_status != 0:
            return prepare_status

        # We know in our build system configuration that the following
        # file suffixes could have come from remote builds.
        # It is ok for this set to be conservatively inclusive.
        # Eliminate inputs that come from the project root ../..,
        # because those are sources or prebuilts.
        remote_artifact_suffixes = {".o", ".a", ".so", ".dylib", ".rlib"}
        download_statuses = self.remote_action.download_inputs(
            lambda path: path.suffix in remote_artifact_suffixes
            and not str(path).startswith(str(self.remote_action.exec_root_rel))
        )
        for path, status in download_statuses.items():
            if status.returncode != 0:
                msg(f"Failed to download input: {path}\n{status.stderr_text}")
                return status.returncode

        # don't bother with remote action preparation
        # or any of the remote action features.
        export_dir = self.miscomparison_export_dir
        command = cl_utils.auto_env_prefix_command(
            _filter_local_command(self.original_command)
        )
        if self.check_determinism:
            self.vmsg("Comparing two local runs of the original command.")

            output_files = list(self._remote_output_files())

            max_attempts = self.determinism_attempts
            # For b/328756843, increase repetition count for hard-to-reproduce cases.
            override_attempts = fuchsia.determinism_repetitions(output_files)
            if override_attempts is not None:
                msg(
                    f"Notice: Overriding number of determinism repetitions: {override_attempts}"
                )
                max_attempts = override_attempts

            command = fuchsia.check_determinism_command(
                exec_root=self.exec_root_rel,
                outputs=output_files,
                command=command,
                max_attempts=max_attempts,
                miscomparison_export_dir=(
                    export_dir / self.build_subdir if export_dir else None
                ),
                label=self.label,
            )

        exit_code = subprocess.call(command, cwd=self.working_dir)

        # Optional: on determinism failures, copy data.
        if exit_code != 0 and self.check_determinism and export_dir:
            # Compute the inputs that would have been used for remote execution
            if not self.remote_action:
                self.prepare()
            # Check determinism script already copies outputs, we just copy the inputs.
            with cl_utils.chdir_cm(self.exec_root):
                for f in self.remote_action.inputs_relative_to_project_root:
                    cl_utils.copy_preserve_subpath(f, export_dir)

        return exit_code

    def run(self) -> int:
        if self.local_only:
            return self.run_local()
        else:
            return self.run_remote()


def main(argv: Sequence[str]) -> int:
    rust_remote_action = RustRemoteAction(
        argv,  # [remote options] -- rustc-compile-command...
        exec_root=remote_action.PROJECT_ROOT,
        working_dir=Path(os.curdir),
        host_platform=fuchsia.HOST_PREBUILT_PLATFORM,
    )
    return rust_remote_action.run()


if __name__ == "__main__":
    sys.exit(main(sys.argv[1:]))
