Proposal
This proposal addresses issue 1. It attempts to solve the symbol versioning
issues that OpenBSD targets have faced. This also affects other targets, but the
most pressing concern lies is in OpenBSD.
The proposed solution is to encode the latest released version of OpenBSD's
-current channel into their targets' target_env cfg. The -current
release channel tracks the latest tip-of-tree change.
Each new versioned release includes all changes in -current up to the moment
the release was made. target_env would embed in its string the latest version
through, possibly, this scheme: openbsd<M>.<m>.
The above scheme would denote the leading version number in <M> and the
trailing version number in <m>. OpenBSD does not follow the SemVer
conventions; version bumping is monotonically increasing.
Note work here follows from MCP 916 2. It builds on the latest developments
in the accompanying Zulip thread 3 4.
Potential use
Embedding the version numbers into target_env would allow downstream crates to
perform compile-time checks in source code. This would allow fine-grained
control over which portions of the crate logic to expose to which targets.
Solving this with manual cfgs is very much possible but would add additional
overhead to the rust-lang/libc build script. The solution this MCP proposes
would move that responsibility to the target maintainer.
Whenever a new release of OpenBSD were to be made available, the corresponding
target_env value for the next rustc release would be updated. The next
nightly rustc release would reflect the new release in the updated value.
Unlike target_env values like those of NTO targets, we would not accumulate
version values across rustc releases. This is because versioning on NTO
targets is due to specific differences across a number of versions.
Versioning in OpenBSBD targets would thus serve to reflect which version of
OpenBSD downstream crates are most likely to support correctly. Older values
would be maintained by OpenBSD ports.
As an example, if some Rust crate decides on supporting only OpenBSD 7.9's ABI,
an overly simple cfg check coud look as follows.
#![cfg_attr(target_os = "openbsd", cfg(target_env = "openbsd7.9"))]
This would mean that the release in which this code would be packaged would only
provide ABI-compatibility guarantees for OpenBSD 7.9.
Prior art
RFC 3750 5 has already addressed similar concerns. It is not yet merged nor
has landed on nightly. This means it will likely be a long way off until we can
use it in rust-lang/libc, the main motivator for this MCP. The target versioning
cfg proposed there does not entirely solve the issue either. It provides a way
of formally setting a baseline supported version for Rust targets but does not
initially implement support for changing such version nor for the cfg to be
backportable and thus usable with differing values on older rustc versions.
RFC 3905 6 seems to pave the way for an ideal solution. It introduces a
version type for certain cfgs along with two PartialOrd-based operators with
which to compare version strings. These efforts, though, are even further away
from solving rust-lang/libc's concerns with OpenBSD targets than RFC 3750. This
RFC does not initially address target versioning and has neither a PoC
implementation nor is in nightly yet. All things considered, it will likely be
another six months until an implementation reaches end users, and possibly over
a year until a new RFC/MCP extends the new cfg system with target versioning
in mind.
Outside the Rust ecosystem, OpenBSD targets in LLVM append the supported release
version to the end of the target tuple denomination.
Target modifiers introduced in RFC 3716 7 were also considered due to the
tight relation between ELF symbol versioning and possibly unsound ABI guarantees
from interfaces that don't exist under certain OS versions. This was discarded
because the impression I had gotten from the RFC was that (1) such target
modifiers were inteded for lower-level purposes, and (2) such modifiers were
meant purely for Rust-native environments. Future possibilities in the RFC did
mention that these compiler flags could be used to solve ABI differences between
Rust and C, but that has not been explored for this MCP. There neither seems to
exist a "built-in" way of having Cargo expose cfgs about target modifiers
issued on the command line. This would mean that build scripts would have to set
their cfgs potentially based off of the (manually parsed) values passed in
CARGO_ENCODED_RUSTFLAGS. There's also the fact this environment variable is
only set when the target matches the host and no target is specified on the
command line or in a Cargo configuration file. This is not ideal for
cross-compilation, which is often used in the rust-lang/libc crate.
Implementation details
The rustc_target crate under compiler in the rust-lang/rust repository would
have to undergo some changes. That crate exposes target details for each of the
in-tree targets, among which OpenBSD systems are found.
-
Adding a new variant to the spec::Env enumeration. Something like
OpenBsdVersion would do just fine, but it's just an implementation detail.
The value would match openbsdx.y, where x would be the leading version
number, and y would consist of the trailing version number. OpenBSD makes
no difference between major and minor versions.
This is more likely to change as the discussion around the MCP progresses,
considering it's a user-facing value.
-
Adding the env field to the Target returned by each of the OpenBSD
targets' target function. This would preferably not be set in the base
specification for OpenBSD, but rather for each individual OpenBSD target.
This is because OpenBSD has deprecated target architectures in the past. This
has happened multiple times 8 since Rust 1.0 9, but thus far has not
affected any of the supported Rust targets 10.
Affected targets would include all currently supported OpenBSD targets. At the
time of writing, this includes the following.
aarch64-unknown-openbsd
i686-unknown-openbsd
powerpc-unknown-openbsd
powerpc64-unknown-openbsd
riscv64gc-unknown-openbsd
sparc64-unknown-openbsd
x86_64-unknown-openbsd
Mentors or Reviewers
@semarie and possibly any of other OpenBSD maintainer in ports/lang/rust.
Process
The main points of the Major Change Process are as follows:
You can read more about Major Change Proposals on forge.
Proposal
This proposal addresses issue 1. It attempts to solve the symbol versioning
issues that OpenBSD targets have faced. This also affects other targets, but the
most pressing concern lies is in OpenBSD.
The proposed solution is to encode the latest released version of OpenBSD's
-currentchannel into their targets'target_envcfg. The-currentrelease channel tracks the latest tip-of-tree change.
Each new versioned release includes all changes in
-currentup to the momentthe release was made.
target_envwould embed in its string the latest versionthrough, possibly, this scheme:
openbsd<M>.<m>.The above scheme would denote the leading version number in
<M>and thetrailing version number in
<m>. OpenBSD does not follow the SemVerconventions; version bumping is monotonically increasing.
Note work here follows from MCP 916 2. It builds on the latest developments
in the accompanying Zulip thread 3 4.
Potential use
Embedding the version numbers into
target_envwould allow downstream crates toperform compile-time checks in source code. This would allow fine-grained
control over which portions of the crate logic to expose to which targets.
Solving this with manual
cfgs is very much possible but would add additionaloverhead to the rust-lang/libc build script. The solution this MCP proposes
would move that responsibility to the target maintainer.
Whenever a new release of OpenBSD were to be made available, the corresponding
target_envvalue for the nextrustcrelease would be updated. The nextnightly
rustcrelease would reflect the new release in the updated value.Unlike
target_envvalues like those of NTO targets, we would not accumulateversion values across
rustcreleases. This is because versioning on NTOtargets is due to specific differences across a number of versions.
Versioning in OpenBSBD targets would thus serve to reflect which version of
OpenBSD downstream crates are most likely to support correctly. Older values
would be maintained by OpenBSD ports.
As an example, if some Rust crate decides on supporting only OpenBSD 7.9's ABI,
an overly simple
cfgcheck coud look as follows.#![cfg_attr(target_os = "openbsd", cfg(target_env = "openbsd7.9"))]This would mean that the release in which this code would be packaged would only
provide ABI-compatibility guarantees for OpenBSD 7.9.
Prior art
RFC 3750 5 has already addressed similar concerns. It is not yet merged nor
has landed on nightly. This means it will likely be a long way off until we can
use it in rust-lang/libc, the main motivator for this MCP. The target versioning
cfgproposed there does not entirely solve the issue either. It provides a wayof formally setting a baseline supported version for Rust targets but does not
initially implement support for changing such version nor for the
cfgto bebackportable and thus usable with differing values on older
rustcversions.RFC 3905 6 seems to pave the way for an ideal solution. It introduces a
version type for certain
cfgs along with twoPartialOrd-based operators withwhich to compare version strings. These efforts, though, are even further away
from solving rust-lang/libc's concerns with OpenBSD targets than RFC 3750. This
RFC does not initially address target versioning and has neither a PoC
implementation nor is in nightly yet. All things considered, it will likely be
another six months until an implementation reaches end users, and possibly over
a year until a new RFC/MCP extends the new
cfgsystem with target versioningin mind.
Outside the Rust ecosystem, OpenBSD targets in LLVM append the supported release
version to the end of the target tuple denomination.
Target modifiers introduced in RFC 3716 7 were also considered due to the
tight relation between ELF symbol versioning and possibly unsound ABI guarantees
from interfaces that don't exist under certain OS versions. This was discarded
because the impression I had gotten from the RFC was that (1) such target
modifiers were inteded for lower-level purposes, and (2) such modifiers were
meant purely for Rust-native environments. Future possibilities in the RFC did
mention that these compiler flags could be used to solve ABI differences between
Rust and C, but that has not been explored for this MCP. There neither seems to
exist a "built-in" way of having Cargo expose
cfgs about target modifiersissued on the command line. This would mean that build scripts would have to set
their
cfgs potentially based off of the (manually parsed) values passed inCARGO_ENCODED_RUSTFLAGS. There's also the fact this environment variable isonly set when the target matches the host and no target is specified on the
command line or in a Cargo configuration file. This is not ideal for
cross-compilation, which is often used in the rust-lang/libc crate.
Implementation details
The
rustc_targetcrate undercompilerin the rust-lang/rust repository wouldhave to undergo some changes. That crate exposes target details for each of the
in-tree targets, among which OpenBSD systems are found.
Adding a new variant to the
spec::Envenumeration. Something likeOpenBsdVersionwould do just fine, but it's just an implementation detail.The value would match
openbsdx.y, wherexwould be the leading versionnumber, and
ywould consist of the trailing version number. OpenBSD makesno difference between major and minor versions.
This is more likely to change as the discussion around the MCP progresses,
considering it's a user-facing value.
Adding the
envfield to theTargetreturned by each of the OpenBSDtargets'
targetfunction. This would preferably not be set in the basespecification for OpenBSD, but rather for each individual OpenBSD target.
This is because OpenBSD has deprecated target architectures in the past. This
has happened multiple times 8 since Rust 1.0 9, but thus far has not
affected any of the supported Rust targets 10.
Affected targets would include all currently supported OpenBSD targets. At the
time of writing, this includes the following.
aarch64-unknown-openbsdi686-unknown-openbsdpowerpc-unknown-openbsdpowerpc64-unknown-openbsdriscv64gc-unknown-openbsdsparc64-unknown-openbsdx86_64-unknown-openbsdMentors or Reviewers
@semarie and possibly any of other OpenBSD maintainer in
ports/lang/rust.Process
The main points of the Major Change Process are as follows:
writing
@rustbot secondor kickoff a team FCP with@rfcbot fcp $RESOLUTION.Proposals, Approvals and Stabilization
docs for when a second is sufficient, or when a full team FCP is required.
solved.
Once all concerns are resolved, the 10 day countdown is restarted.
outstanding concern, the MCP is considered approved.
You can read more about Major Change Proposals on forge.
Footnotes
How to deal with breaking changes on platform ? [BSDs related] libc#570 ↩
Split the
-openbsd*targets by version #916 ↩https://rust-lang.zulipchat.com/#narrow/channel/233931-t-compiler.2Fmajor-changes/topic/Split.20the.20.60-openbsd.2A.60.20targets.20by.20version.20compiler-team.23916/near/540674855 ↩
https://rust-lang.zulipchat.com/#narrow/channel/233931-t-compiler.2Fmajor-changes/topic/Split.20the.20.60-openbsd.2A.60.20targets.20by.20version.20compiler-team.23916/near/602198382 ↩
RFC: cfg_target_version rfcs#3750 ↩
Version-typed cfgs rfcs#3905 ↩
[RFC] Target Modifiers rfcs#3716 ↩
The
armishport was discontinued on Sep. 2016,aviionwas discontinuedon May 2015,
hppa64was discontinued on Mar. 2016,loongsonwasdiscontinued on May 2026,
sgiwas discontinued on May 2021,socppcwasdiscontinued on Oct. 2015,
sparcwas discontinued on Mar. 2016,vaxwas discontinued on Mar. 2016, and
zauruswas discontinued on Sep. 2016. ↩Assumming Rust 1.0 to have been released on May 15, 2015. ↩
Except maybe
socppc, though it seems the existingpowerpc-unknown-openbsdRust target should cover bothsocppcports andmacppcports (the latter of which is still supported upstream.) ↩