Skip to content

Encode OpenBSD -current version in targets' target_env #1018

Description

@dybucc

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.

  1. 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.

  2. 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:

  • File an issue describing the proposal.
  • A compiler team member who is knowledgeable in the area can second by
    writing @rustbot second or kickoff a team FCP with @rfcbot fcp $RESOLUTION.
  • Once an MCP is seconded, the Final Comment Period begins.
    • Final Comment Period lasts for 10 days after all outstanding concerns are
      solved.
    • Outstanding concerns will block the Final Comment Period from finishing.
      Once all concerns are resolved, the 10 day countdown is restarted.
    • If no concerns are raised after 10 days since the resolution of the last
      outstanding concern, the MCP is considered approved.

You can read more about Major Change Proposals on forge.

Footnotes

  1. How to deal with breaking changes on platform ? [BSDs related] libc#570 2 3

  2. Split the -openbsd* targets by version #916 2

  3. 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 2

  4. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    T-compilerAdd this label so rfcbot knows to poll the compiler teammajor-changeA proposal to make a major change to rustc

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions