Description
Proposal
Summary and problem statement
Target names (sometimes called target "triples" despite having two, four, or five components) have a field for the "vendor" of a system. This field is vestigial, and ideally Rust code should never need to match on it to distinguish targets. All modern targets are effectively distinguished by architecture, OS, environment, and ABI, with the exception of a few target names invented solely for Rust. We should not use the target_vendor
field to distinguish future targets; we should distinguish targets using more semantically meaningful fields.
Motivation, use-cases, and solution sketches
I propose to prevent any new targets from being distinguished solely by "vendor", and I propose to deprecate the target_vendor
field, with a transition plan for the Rust-originated targets that currently exist. (I do not propose to change the name of any existing target.)
The existing Rust-originated targets where target_vendor
matters:
Windows UWP targets use target_vendor
as the only distinction from the corresponding non-UWP Windows targets:
aarch64-pc-windows-msvc
aarch64-uwp-windows-msvc
i686-pc-windows-gnu
i686-uwp-windows-gnu
i686-pc-windows-msvc
i686-uwp-windows-msvc
thumbv7a-pc-windows-msvc
thumbv7a-uwp-windows-msvc
x86_64-pc-windows-gnu
x86_64-uwp-windows-gnu
x86_64-pc-windows-msvc
x86_64-uwp-windows-msvc
For these targets, I propose to set target_abi = "uwp"
, and encourage code to use that instead. I don't propose to change the name of these targets.
The SGX target, x86_64-fortanix-unknown-sgx
, uses target_vendor
to distinguish between the fortanix SGX API/ABI and a hypothetical future SGX API/ABI from another vendor. I propose to set target_abi = "fortanix"
for this target, as in practice that's the purpose this field serves.
We have a deprecated Solaris compatibility target, x86_64-sun-solaris
, similar to x86_64-pc-solaris
. I propose to leave this target untouched, as it's already deprecated; that transition should continue as planned.
Finally, Apple targets set target_vendor = "apple"
, and some code uses this to match both iOS and macOS. We could optionally add target_family = "apple"
for these targets, in addition to the existing target_family = "unix"
. Rust supports having multiple "family" values set, though this has the possibility of breaking fragile build scripts that match the entire value of CARGO_CFG_TARGET_FAMILY
rather than treating it as a list.
Once target_abi
is stable and the UWP and Fortanix targets set target_abi
, and the Apple targets set target_family
, I propose to carefully deprecate the target_vendor
field, by adding a warn-by-default future-compatibility lint. target_vendor
should continue to work for several years. We may eventually choose to remove it in a future edition.
We may optionally choose to start warning about uses of target_vendor
that don't look for uwp
or fortanix
early, and then just suppress warnings about checks for those two values until target_abi
is stable.
For future new targets, I propose to omit the "vendor" component entirely unless needed for compatibility with naming already used by other existing widespread toolchains. Whenever we create a new target name, we should omit the "vendor" element entirely, as we did for wasm32-wasi
.
Links and related work
Target "triples" originated with autotools. The maintainer of autoconf, @zackw, wrote about the vendor field at https://internals.rust-lang.org/t/expand-targets-acceptable-to-rustc/14885/26 👍
- The VENDOR component of a GNU "canonical system name" is vestigial. It exists because there was a brief period in the late 1980s/early 1990s where there were a bunch of Unix workstation vendors all putting out kit based on the Motorola 68xxx CPU, with operating systems identifying themselves as "Unix System V", but providing different C-level programming environments. So
m68k-foonly-sysv
andm68k-barley-sysv
could have been meaningfully different. Nobody does this anymore, because the marketing value of giving your company's operating system its own name became obvious almost immediately.
If you look at how GCC's configure.ac, for instance, processes canonical system names, you will see that most of the time it looks only at$(host|target)_cpu
or at$(host|target)_os
, and the rest of the time it uses shell glob patterns that ignore the vendor field.
I would recommend documenting that#[cfg(target_vendor = ...)]
is supported for completeness and (as far as the Rust Project knows) is not useful for distinguishing between any two currently supported systems.
Initial people involved
I don't believe this will require a formal "project", just a few PRs, which I'll either write or coordinate. However, I'd like to seek consensus on this change before beginning work on it.
What happens now?
This issue is part of the experimental MCP process described in RFC 2936. Once this issue is filed, a Zulip topic will be opened for discussion, and the lang-team will review open MCPs in its weekly triage meetings. You should receive feedback within a week or two.
This issue is not meant to be used for technical discussion. There is a Zulip stream for that. Use this issue to leave procedural comments, such as volunteering to review, indicating that you second the proposal (or third, etc), or raising a concern that you would like to be addressed.