Proposal
This proposal addresses issue 1. It attempts to solve the symbol versioning
conflicts that are explained in that issue thread on OpenBSD targets. The core
of the proposal is simple; Add target versioning information about the supported
OpenBSD -current-channel version. The rest of this MCP expands on how could
this be achived.
Note work here follows from MCP 916 2. It builds on the latest developments
in the accompanying Zulip thread 3 4.
Background
1 refers to a number of situations in which OpenBSD targets have had the
wrong symbols linked to in some target versions. This has been due to some of
the changes in later releases forcing non-backward- nor forward-compatible
changes. Similar issues were also commented on for other systems but the most
pressing concern seems to be on OpenBSD. This MCP attempts to provide an
immediate solution exclusive to those targets. The main context taken into
account here are the C platform bindings provided in the rust-lang/libc crate.
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.
Solving this would allow providing bindings that target a specific baseline
version. This version would ideally be in sync with the officially documented
baseline version for each OpenBSD target in the Rust platform support page.
Solution
Embedding the OpenBSD release version for the -current channel into the
target_env cfg for all OpenBSD targets. This would allow checking in source
code through uses of the cfg system which OpenBSD release is supported for a
given version of rustc. The rust-lang/libc crate, and any other crates
providing bindings to C interfaces, could expose different APIs in code
depending on the value of target_env. This would exploit the fact that
target_env values may differ across versions of rustc.
An example of the value for the target_env cfg would be openbsd7.9. This
example would encode information on release 7.9 of the OpenBSD operating system.
Whenever a new release of OpenBSD were to be made available, the corresponding
target_env value for the next rustc release would be updated. If some new
OpenBSD release were to be made before a Rust stable release were made, then the
value would still be updated. This would be immediately available to nightly
users, but not to stable users. Of course, nightly users would have to wait at
most 24 hours. Othewrise, building Rust from source would deliver an immediate
update. We speak of immediacy here, but no automated solution has been thought
of at present.
Admittedly, this would move the responsibility back to the target maintainer(s).
Still, it would at least provide a baseline version for the supported OpenBSD
target at any given point in time. Considering such concerns were raised by the
target maintainer themselves in 1, this has been initially deemed acceptable.
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
on OpenBSD targets would serve a potential purpose; Gating forward- or
backward-incompatible changes, if such changes were to happen in future
releases.
Differing values of the cfg would then match if the user is using an older
Rust toolchain, possibly provided by the OpenBSD ports themselves. The rustc
changes required for that would be minor, so there should not be much difficulty
associated with the patches over rustc required to accomplish this.
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
Implementation
Implementation details would be concerned with the rustc_target crate under
compiler in the rust-lang/rust repository. That crate exposes target details
for each of the in-tree targets, among which the OpenBSD targets are found. This
MCP would only require two changes.
-
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 3 since Rust 1.0 2, but thus far has not
affected any of the supported Rust targets 4.
Rust support for some OpenBSD target would have to be dropped in the rustc
stable release that would match the latest OpenBSD release, but older rustc
versions (possibly patched by OpenBSD maintainers and packaged as OS-specific
toolchains) could still keep these targets with an older target_env value.
Prior art
RFC 3750 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 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 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.
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
conflicts that are explained in that issue thread on OpenBSD targets. The core
of the proposal is simple; Add target versioning information about the supported
OpenBSD
-current-channel version. The rest of this MCP expands on how couldthis be achived.
Note work here follows from MCP 916 2. It builds on the latest developments
in the accompanying Zulip thread 3 4.
Background
1 refers to a number of situations in which OpenBSD targets have had the
wrong symbols linked to in some target versions. This has been due to some of
the changes in later releases forcing non-backward- nor forward-compatible
changes. Similar issues were also commented on for other systems but the most
pressing concern seems to be on OpenBSD. This MCP attempts to provide an
immediate solution exclusive to those targets. The main context taken into
account here are the C platform bindings provided in the rust-lang/libc crate.
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.
Solving this would allow providing bindings that target a specific baseline
version. This version would ideally be in sync with the officially documented
baseline version for each OpenBSD target in the Rust platform support page.
Solution
Embedding the OpenBSD release version for the
-currentchannel into thetarget_envcfgfor all OpenBSD targets. This would allow checking in sourcecode through uses of the
cfgsystem which OpenBSD release is supported for agiven version of
rustc. The rust-lang/libc crate, and any other cratesproviding bindings to C interfaces, could expose different APIs in code
depending on the value of
target_env. This would exploit the fact thattarget_envvalues may differ across versions ofrustc.An example of the value for the
target_envcfgwould beopenbsd7.9. Thisexample would encode information on release 7.9 of the OpenBSD operating system.
Whenever a new release of OpenBSD were to be made available, the corresponding
target_envvalue for the nextrustcrelease would be updated. If some newOpenBSD release were to be made before a Rust stable release were made, then the
value would still be updated. This would be immediately available to nightly
users, but not to stable users. Of course, nightly users would have to wait at
most 24 hours. Othewrise, building Rust from source would deliver an immediate
update. We speak of immediacy here, but no automated solution has been thought
of at present.
Admittedly, this would move the responsibility back to the target maintainer(s).
Still, it would at least provide a baseline version for the supported OpenBSD
target at any given point in time. Considering such concerns were raised by the
target maintainer themselves in 1, this has been initially deemed acceptable.
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
on OpenBSD targets would serve a potential purpose; Gating forward- or
backward-incompatible changes, if such changes were to happen in future
releases.
Differing values of the
cfgwould then match if the user is using an olderRust toolchain, possibly provided by the OpenBSD ports themselves. The
rustcchanges required for that would be minor, so there should not be much difficulty
associated with the patches over
rustcrequired to accomplish this.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-openbsdImplementation
Implementation details would be concerned with the
rustc_targetcrate undercompilerin the rust-lang/rust repository. That crate exposes target detailsfor each of the in-tree targets, among which the OpenBSD targets are found. This
MCP would only require two changes.
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 3 since Rust 1.0 2, but thus far has not
affected any of the supported Rust targets 4.
Rust support for some OpenBSD target would have to be dropped in the
rustcstable release that would match the latest OpenBSD release, but older
rustcversions (possibly patched by OpenBSD maintainers and packaged as OS-specific
toolchains) could still keep these targets with an older
target_envvalue.Prior art
RFC 3750 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 seems to pave the way for an ideal solution. It introduces a version
type for certain
cfgs along with twoPartialOrd-based operators with whichto 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 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.
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:
writing
@rustbot secondor kickoff a team FCP with@rfcbot fcp $RESOLUTION.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 ↩ ↩2 ↩3
Split the
-openbsd*targets by version #916 ↩ ↩2https://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 ↩ ↩2
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 ↩ ↩2