blob: d519576087e97d2d6bd85c4004c4081ba253bda9 [file] [log] [blame]
"""Utility functions for the cargo rules"""
load("//rust/platform:triple.bzl", "triple")
load("//rust/platform:triple_mappings.bzl", "system_to_binary_ext")
_CPU_ARCH_ERROR_MSG = """\
Command failed with exit code '{code}': {args}
----------stdout:
{stdout}
----------stderr:
{stderr}
"""
def _query_cpu_architecture(repository_ctx, expected_archs, is_windows = False):
"""Detect the host CPU architecture
Args:
repository_ctx (repository_ctx): The repository rule's context object
expected_archs (list): A list of expected architecture strings
is_windows (bool, optional): If true, the cpu lookup will use the windows method (`wmic` vs `uname`)
Returns:
str: The host's CPU architecture
"""
if is_windows:
arguments = ["wmic", "os", "get", "osarchitecture"]
else:
arguments = ["uname", "-m"]
result = repository_ctx.execute(arguments)
if result.return_code:
fail(_CPU_ARCH_ERROR_MSG.format(
code = result.return_code,
args = arguments,
stdout = result.stdout,
stderr = result.stderr,
))
if is_windows:
# Example output:
# OSArchitecture
# 64-bit
lines = result.stdout.split("\n")
arch = lines[1].strip()
# Translate 64-bit to a compatible rust platform
# https://doc.rust-lang.org/nightly/rustc/platform-support.html
if arch == "64-bit":
arch = "x86_64"
else:
arch = result.stdout.strip("\n")
# Correct the arm architecture for macos
if "mac" in repository_ctx.os.name and arch == "arm64":
arch = "aarch64"
if not arch in expected_archs:
fail("{} is not a expected cpu architecture {}\n{}".format(
arch,
expected_archs,
result.stdout,
))
return arch
def get_host_triple(repository_ctx, abi = None):
"""Query host information for the appropriate triples for the crate_universe resolver
Args:
repository_ctx (repository_ctx): The rule's repository_ctx
abi (str): Since there's no consistent way to check for ABI, this info
may be explicitly provided
Returns:
struct: A triple struct, see `@rules_rust//rust/platform:triple.bzl`
"""
# Detect the host's cpu architecture
supported_architectures = {
"linux": ["aarch64", "x86_64"],
"macos": ["aarch64", "x86_64"],
"windows": ["x86_64"],
}
if "linux" in repository_ctx.os.name:
cpu = _query_cpu_architecture(repository_ctx, supported_architectures["linux"])
return triple("{}-unknown-linux-{}".format(
cpu,
abi or "gnu",
))
if "mac" in repository_ctx.os.name:
cpu = _query_cpu_architecture(repository_ctx, supported_architectures["macos"])
return triple("{}-apple-darwin".format(cpu))
if "win" in repository_ctx.os.name:
cpu = _query_cpu_architecture(repository_ctx, supported_architectures["windows"], True)
return triple("{}-pc-windows-{}".format(
cpu,
abi or "msvc",
))
fail("Unhandled host os: {}", repository_ctx.os.name)
def _resolve_repository_template(
template,
abi = None,
arch = None,
system = None,
tool = None,
triple = None,
vendor = None,
version = None):
"""Render values into a repository template string
Args:
template (str): The template to use for rendering
abi (str, optional): The host ABI
arch (str, optional): The host CPU architecture
system (str, optional): The host system name
tool (str, optional): The tool to expect in the particular repository.
Eg. `cargo`, `rustc`, `stdlib`.
triple (str, optional): The host triple
vendor (str, optional): The host vendor name
version (str, optional): The Rust version used in the toolchain.
Returns:
string: The resolved template string based on the given parameters
"""
if abi:
template = template.replace("{abi}", abi)
if arch:
template = template.replace("{arch}", arch)
if system:
template = template.replace("{system}", system)
if tool:
template = template.replace("{tool}", tool)
if triple:
template = template.replace("{triple}", triple)
if vendor:
template = template.replace("{vendor}", vendor)
if version:
template = template.replace("{version}", version)
return template
def get_rust_tools(cargo_template, rustc_template, host_triple, version):
"""Retrieve `cargo` and `rustc` labels based on the host triple.
Args:
cargo_template (str): A template used to identify the label of the host `cargo` binary.
rustc_template (str): A template used to identify the label of the host `rustc` binary.
host_triple (struct): The host's triple. See `@rules_rust//rust/platform:triple.bzl`.
version (str): The version of Cargo+Rustc to use.
Returns:
struct: A struct containing the labels of expected tools
"""
extension = system_to_binary_ext(host_triple.system)
cargo_label = Label(_resolve_repository_template(
template = cargo_template,
version = version,
triple = host_triple.triple,
arch = host_triple.arch,
vendor = host_triple.vendor,
system = host_triple.system,
abi = host_triple.abi,
tool = "cargo" + extension,
))
rustc_label = Label(_resolve_repository_template(
template = rustc_template,
version = version,
triple = host_triple.triple,
arch = host_triple.arch,
vendor = host_triple.vendor,
system = host_triple.system,
abi = host_triple.abi,
tool = "rustc" + extension,
))
return struct(
cargo = cargo_label,
rustc = rustc_label,
)