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

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

  • 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. Split the -openbsd* targets by version #916

  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

  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

  5. RFC: cfg_target_version rfcs#3750

  6. Version-typed cfgs rfcs#3905

  7. [RFC] Target Modifiers rfcs#3716

  8. The armish port was discontinued on Sep. 2016, aviion was discontinued
    on May 2015, hppa64 was discontinued on Mar. 2016, loongson was
    discontinued on May 2026, sgi was discontinued on May 2021, socppc was
    discontinued on Oct. 2015, sparc was discontinued on Mar. 2016, vax
    was discontinued on Mar. 2016, and zaurus was discontinued on Sep. 2016.

  9. Assumming Rust 1.0 to have been released on May 15, 2015.

  10. Except maybe socppc, though it seems the existing
    powerpc-unknown-openbsd Rust target should cover both socppc ports and
    macppc ports (the latter of which is still supported upstream.)

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 rustcmajor-change-acceptedA major change proposal that was acceptedto-announceAnnounce this issue on triage meeting

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions