blob: 139015da896a88670285ab0129ea8df68bff682a [file] [log] [blame]
"""Helpers for constructing supported Rust platform triples"""
load("//rust/platform:triple.bzl", "triple")
def _support(*, std = False, host_tools = False):
"""Identify the type of support an associated platform triple has.
The source of truth is:
https://doc.rust-lang.org/nightly/rustc/platform-support.html
Args:
std (bool, optional): Whether or not platform has a standard library artifact.
host_tools (bool, optional): Whether or not platform has host tools artifacts.
Returns:
struct: The parameters above.
"""
return struct(
std = std,
host_tools = host_tools,
)
# All T1 Platforms should be supported, but aren't, see inline notes.
SUPPORTED_T1_PLATFORM_TRIPLES = {
"aarch64-apple-darwin": _support(std = True, host_tools = True),
"aarch64-unknown-linux-gnu": _support(std = True, host_tools = True),
"aarch64-unknown-nixos-gnu": _support(std = True, host_tools = True), # Same as `aarch64-unknown-linux-gnu` but with `@platforms//os:nixos`.
"i686-apple-darwin": _support(std = True, host_tools = True),
"i686-pc-windows-msvc": _support(std = True, host_tools = True),
"i686-unknown-linux-gnu": _support(std = True, host_tools = True),
"x86_64-apple-darwin": _support(std = True, host_tools = True),
"x86_64-pc-windows-msvc": _support(std = True, host_tools = True),
"x86_64-unknown-linux-gnu": _support(std = True, host_tools = True),
"x86_64-unknown-nixos-gnu": _support(std = True, host_tools = True), # Same as `x86_64-unknown-linux-gnu` but with `@platforms//os:nixos`.
# N.B. These "alternative" envs are not supported, as bazel cannot distinguish between them
# and others using existing @platforms// config_values
#
#"i686-pc-windows-gnu",
#"x86_64-pc-windows-gnu",
}
# Some T2 Platforms are supported, provided we have mappings to `@platforms//...` entries.
# See `@rules_rust//rust/platform:triple_mappings.bzl` for the complete list.
SUPPORTED_T2_PLATFORM_TRIPLES = {
"aarch64-apple-ios": _support(std = True, host_tools = False),
"aarch64-apple-ios-sim": _support(std = True, host_tools = False),
"aarch64-fuchsia": _support(std = True, host_tools = False),
"aarch64-linux-android": _support(std = True, host_tools = False),
"aarch64-pc-windows-msvc": _support(std = True, host_tools = True),
"arm-unknown-linux-gnueabi": _support(std = True, host_tools = True),
"armv7-linux-androideabi": _support(std = True, host_tools = False),
"armv7-unknown-linux-gnueabi": _support(std = True, host_tools = True),
"i686-linux-android": _support(std = True, host_tools = False),
"i686-unknown-freebsd": _support(std = True, host_tools = False),
"powerpc-unknown-linux-gnu": _support(std = True, host_tools = True),
"riscv32imc-unknown-none-elf": _support(std = True, host_tools = False),
"riscv64gc-unknown-none-elf": _support(std = True, host_tools = False),
"s390x-unknown-linux-gnu": _support(std = True, host_tools = True),
"thumbv7em-none-eabi": _support(std = True, host_tools = False),
"thumbv8m.main-none-eabi": _support(std = True, host_tools = False),
"wasm32-unknown-unknown": _support(std = True, host_tools = False),
"wasm32-wasi": _support(std = True, host_tools = False),
"x86_64-apple-ios": _support(std = True, host_tools = False),
"x86_64-fuchsia": _support(std = True, host_tools = False),
"x86_64-linux-android": _support(std = True, host_tools = False),
"x86_64-unknown-freebsd": _support(std = True, host_tools = True),
"x86_64-unknown-none": _support(std = True, host_tools = False),
}
_T3_PLATFORM_TRIPLES = {
"aarch64-unknown-nto-qnx710": _support(std = True, host_tools = False),
"wasm64-unknown-unknown": _support(std = False, host_tools = False),
}
# The only T3 triples that are supported are ones with at least a stdlib
# artifact. However, it can be useful to know of additional triples so
# this list exists separate from the full list above.
SUPPORTED_T3_PLATFORM_TRIPLES = {
triple: support
for triple, support in _T3_PLATFORM_TRIPLES.items()
if support.std
}
SUPPORTED_PLATFORM_TRIPLES = sorted(
SUPPORTED_T1_PLATFORM_TRIPLES.keys() + SUPPORTED_T2_PLATFORM_TRIPLES.keys() + SUPPORTED_T3_PLATFORM_TRIPLES.keys(),
)
# Represents all platform triples `rules_rust` is configured to handle in some way.
# Note that with T3 platforms some artifacts may not be available which can lead to
# failures in the analysis phase. This list should be used sparingly.
ALL_PLATFORM_TRIPLES = SUPPORTED_T1_PLATFORM_TRIPLES.keys() + SUPPORTED_T2_PLATFORM_TRIPLES.keys() + _T3_PLATFORM_TRIPLES.keys()
# CPUs that map to a `@platforms//cpu` entry
_CPU_ARCH_TO_BUILTIN_PLAT_SUFFIX = {
"aarch64": "aarch64",
"arm": "arm",
"arm64e": "arm64e",
"armv7": "armv7",
"armv7s": None,
"asmjs": None,
"i386": "i386",
"i586": None,
"i686": "x86_32",
"le32": None,
"mips": None,
"mipsel": None,
"powerpc": "ppc",
"powerpc64": None,
"powerpc64le": None,
"riscv32": "riscv32",
"riscv32imc": "riscv32",
"riscv64": "riscv64",
"riscv64gc": "riscv64",
"s390": None,
"s390x": "s390x",
"thumbv6m": "armv6-m",
"thumbv7em": "armv7e-m",
"thumbv7m": "armv7-m",
"thumbv8m.main": "armv8-m",
"wasm32": "wasm32",
"wasm64": "wasm64",
"x86_64": "x86_64",
}
# Systems that map to a "@platforms//os entry
_SYSTEM_TO_BUILTIN_SYS_SUFFIX = {
"android": "android",
"bitrig": None,
"darwin": "osx",
"dragonfly": None,
"eabi": "none",
"eabihf": "none",
"emscripten": None,
"freebsd": "freebsd",
"fuchsia": "fuchsia",
"ios": "ios",
"linux": "linux",
"nacl": None,
"netbsd": None,
"nixos": "nixos",
"none": "none",
"nto": "qnx",
"openbsd": "openbsd",
"solaris": None,
"unknown": None,
"wasi": None,
"windows": "windows",
}
_SYSTEM_TO_BINARY_EXT = {
"android": "",
"darwin": "",
"eabi": "",
"eabihf": "",
"emscripten": ".js",
"freebsd": "",
"fuchsia": "",
"ios": "",
"linux": "",
"nixos": "",
"none": "",
"nto": "",
# This is currently a hack allowing us to have the proper
# generated extension for the wasm target, similarly to the
# windows target
"unknown": ".wasm",
"wasi": ".wasm",
"windows": ".exe",
}
_SYSTEM_TO_STATICLIB_EXT = {
"android": ".a",
"darwin": ".a",
"eabi": ".a",
"eabihf": ".a",
"emscripten": ".js",
"freebsd": ".a",
"fuchsia": ".a",
"ios": ".a",
"linux": ".a",
"nixos": ".a",
"none": ".a",
"nto": ".a",
"unknown": "",
"wasi": "",
"windows": ".lib",
}
_SYSTEM_TO_DYLIB_EXT = {
"android": ".so",
"darwin": ".dylib",
"eabi": ".so",
"eabihf": ".so",
"emscripten": ".js",
"freebsd": ".so",
"fuchsia": ".so",
"ios": ".dylib",
"linux": ".so",
"nixos": ".so",
"none": ".so",
"nto": ".a",
"unknown": ".wasm",
"wasi": ".wasm",
"windows": ".dll",
}
# See https://github.com/rust-lang/rust/blob/master/src/libstd/build.rs
_SYSTEM_TO_STDLIB_LINKFLAGS = {
# NOTE: Rust stdlib `build.rs` treats android as a subset of linux, rust rules treat android
# as its own system.
"android": ["-ldl", "-llog"],
"bitrig": [],
# TODO(gregbowyer): If rust stdlib is compiled for cloudabi with the backtrace feature it
# includes `-lunwind` but this might not actually be required.
# I am not sure which is the common configuration or how we encode it as a link flag.
"cloudabi": ["-lunwind", "-lc", "-lcompiler_rt"],
"darwin": ["-lSystem", "-lresolv"],
"dragonfly": ["-lpthread"],
"eabi": [],
"eabihf": [],
"emscripten": [],
# TODO(bazelbuild/rules_cc#75):
#
# Right now bazel cc rules does not specify the exact flag setup needed for calling out system
# libs, that is we dont know given a toolchain if it should be, for example,
# `-lxxx` or `/Lxxx` or `xxx.lib` etc.
#
# We include the flag setup as they are _commonly seen_ on various platforms with a cc_rules
# style override for people doing things like gnu-mingw on windows.
#
# If you are reading this ... sorry! set the env var `BAZEL_RUST_STDLIB_LINKFLAGS` to
# what you need for your specific setup, for example like so
# `BAZEL_RUST_STDLIB_LINKFLAGS="-ladvapi32:-lws2_32:-luserenv"`
"freebsd": ["-lexecinfo", "-lpthread"],
"fuchsia": ["-lzircon", "-lfdio"],
"illumos": ["-lsocket", "-lposix4", "-lpthread", "-lresolv", "-lnsl", "-lumem"],
"ios": ["-lSystem", "-lobjc", "-Wl,-framework,Security", "-Wl,-framework,Foundation", "-lresolv"],
# TODO: This ignores musl. Longer term what does Bazel think about musl?
"linux": ["-ldl", "-lpthread"],
"nacl": [],
"netbsd": ["-lpthread", "-lrt"],
"nixos": ["-ldl", "-lpthread"], # Same as `linux`.
"none": [],
"nto": [],
"openbsd": ["-lpthread"],
"solaris": ["-lsocket", "-lposix4", "-lpthread", "-lresolv"],
"unknown": [],
"uwp": ["ws2_32.lib"],
"wasi": [],
"windows": ["advapi32.lib", "ws2_32.lib", "userenv.lib", "Bcrypt.lib"],
}
def cpu_arch_to_constraints(cpu_arch, *, system = None):
"""Returns a list of contraint values which represents a triple's CPU.
Args:
cpu_arch (str): The architecture to match constraints for
system (str, optional): The system for the associated ABI value.
Returns:
List: A list of labels to constraint values
"""
if cpu_arch not in _CPU_ARCH_TO_BUILTIN_PLAT_SUFFIX:
fail("CPU architecture \"{}\" is not supported by rules_rust".format(cpu_arch))
plat_suffix = _CPU_ARCH_TO_BUILTIN_PLAT_SUFFIX[cpu_arch]
# Patch armv7e-m to mf if hardfloat abi is selected
if plat_suffix == "armv7e-m" and system == "eabihf":
plat_suffix = "armv7e-mf"
return ["@platforms//cpu:{}".format(plat_suffix)]
def vendor_to_constraints(_vendor):
# TODO(acmcarther): Review:
#
# My current understanding is that vendors can't have a material impact on
# constraint sets.
return []
def system_to_constraints(system):
if system not in _SYSTEM_TO_BUILTIN_SYS_SUFFIX:
fail("System \"{}\" is not supported by rules_rust".format(system))
sys_suffix = _SYSTEM_TO_BUILTIN_SYS_SUFFIX[system]
return ["@platforms//os:{}".format(sys_suffix)]
def abi_to_constraints(abi, *, arch = None, system = None):
"""Return a list of constraint values which represents a triple's ABI.
Note that some ABI values require additional info to accurately match a set of constraints.
Args:
abi (str): The abi value to match constraints for
arch (str, optional): The architecture for the associated ABI value.
system (str, optional): The system for the associated ABI value.
Returns:
List: A list of labels to constraint values
"""
all_abi_constraints = []
# add constraints for MUSL static compilation and linking
# to separate the MUSL from the non-MUSL toolchain on x86_64
# if abi == "musl" and system == "linux" and arch == "x86_64":
# all_abi_constraints.append("//rust/platform/constraints:musl_on")
# add constraints for iOS + watchOS simulator and device triples
if system in ["ios", "watchos"]:
if arch == "x86_64" or abi == "sim":
all_abi_constraints.append("@build_bazel_apple_support//constraints:simulator")
else:
all_abi_constraints.append("@build_bazel_apple_support//constraints:device")
# TODO(bazelbuild/platforms#38): Implement when C++ toolchain is more mature and we
# figure out how they're doing this
return all_abi_constraints
def triple_to_system(target_triple):
"""Returns a system name for a given platform triple
**Deprecated**: Use triple() from triple.bzl directly.
Args:
target_triple (str): A platform triple. eg: `x86_64-unknown-linux-gnu`
Returns:
str: A system name
"""
if type(target_triple) == "string":
target_triple = triple(target_triple)
return target_triple.system
def triple_to_arch(target_triple):
"""Returns a system architecture name for a given platform triple
**Deprecated**: Use triple() from triple.bzl directly.
Args:
target_triple (str): A platform triple. eg: `x86_64-unknown-linux-gnu`
Returns:
str: A cpu architecture
"""
if type(target_triple) == "string":
target_triple = triple(target_triple)
return target_triple.arch
def triple_to_abi(target_triple):
"""Returns a system abi name for a given platform triple
**Deprecated**: Use triple() from triple.bzl directly.
Args:
target_triple (str): A platform triple. eg: `x86_64-unknown-linux-gnu`
Returns:
str: The triple's abi
"""
if type(target_triple) == "string":
target_triple = triple(target_triple)
return target_triple.system
def system_to_dylib_ext(system):
return _SYSTEM_TO_DYLIB_EXT[system]
def system_to_staticlib_ext(system):
return _SYSTEM_TO_STATICLIB_EXT[system]
def system_to_binary_ext(system):
return _SYSTEM_TO_BINARY_EXT[system]
def system_to_stdlib_linkflags(system):
return _SYSTEM_TO_STDLIB_LINKFLAGS[system]
def triple_to_constraint_set(target_triple):
"""Returns a set of constraints for a given platform triple
Args:
target_triple (str): A platform triple. eg: `x86_64-unknown-linux-gnu`
Returns:
list: A list of constraints (each represented by a list of strings)
"""
if target_triple == "wasm32-wasi":
return [
"@platforms//cpu:wasm32",
"@platforms//os:wasi",
]
if target_triple == "wasm32-unknown-unknown":
return [
"@platforms//cpu:wasm32",
"@platforms//os:none",
]
if target_triple == "wasm64-unknown-unknown":
return [
"@platforms//cpu:wasm64",
"@platforms//os:none",
]
triple_struct = triple(target_triple)
constraint_set = []
constraint_set += cpu_arch_to_constraints(
triple_struct.arch,
system = triple_struct.system,
)
constraint_set += vendor_to_constraints(triple_struct.vendor)
constraint_set += system_to_constraints(triple_struct.system)
constraint_set += abi_to_constraints(
triple_struct.abi,
arch = triple_struct.arch,
system = triple_struct.system,
)
return constraint_set