Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: Add target_abi configuration #2992

Merged
merged 3 commits into from
Jan 13, 2021
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 112 additions & 0 deletions text/0000-cfg-target-abi.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
- Feature Name: `cfg-target-abi`
- Start Date: 2020-09-27
- RFC PR: [rust-lang/rfcs#2992](https://github.com/rust-lang/rfcs/pull/2992)
- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000)

# Summary
[summary]: #summary

This proposes a new `cfg`: `target_abi`, which specifies certain aspects of the
target's [Application Binary Interface (ABI)][abi]. This also adds a
`CARGO_CFG_TARGET_ABI` environment variable for parity with other
`CARGO_CFG_TARGET_*` variables.

# Motivation
[motivation]: #motivation

Certain targets are only differentiated by their ABI. For example: the `ios` OS
in combination with the `macabi` ABI denotes targeting Mac Catalyst (iOS on
macOS). The non-`macabi` `x86_64-apple-ios` target is not for Mac Catalyst and
instead is for the iOS simulator, which is a very different environment.

It is not currently possible to `#[cfg]` against a certain target ABI without
a `build.rs` script to emit a custom `cfg` based on the `TARGET` environment
variable. This is not ideal because:

- Adding a build script increases compile time and makes a crate incompatible
with certain build systems.

- Checking `TARGET` is error prone, mainly because the ABI often follows
`target_env` without separation.

# Guide-level explanation
[guide-level-explanation]: #guide-level-explanation

This would act like [existing `target_*` configurations][cfg-options].

For example: if one had a module with bindings to
[Apple's AppKit](https://developer.apple.com/documentation/appkit), this feature
could be used to ensure the module is available when targeting regular macOS and
Mac Catalyst.

```rust
#[cfg(any(
target_os = "macos",
all(
target_os = "ios",
target_abi = "macabi",
),
))]
pub mod app_kit;
```

This configuration option would also be usable as
`#[cfg_attr(target_abi = "...", attr)]`.

# Reference-level explanation
[reference-level-explanation]: #reference-level-explanation

`target_abi` is a key-value option set once with the target's ABI. The value is
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does rustc already have the concept of target ABI internally? If not it seems really important to spell out how exactly this is defined. The concept of ABIs is really poorly understood by developers in my experience. Obviously there's a 1:1 mapping of target : ABI, but the inverse mapping is a little fuzzy to me and I'm not sure how useful it is in practice.

For example, I'm not really aware of an existing convention for talking about the "x86-64 System V ABI" despite it being the ABI used in both x86-64 Linux and macOS.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Specifically what I'm interested in is the component that comes after target_env in the triple string. What it indicates varies greatly between different targets. On some targets, it indicates the availability of hardware floats (e.g. eabihf for embedded abi, hardware float). On others, it indicates the running environment (e.g. x86_64-apple-ios-macabi for iOS apps that target macOS).

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To answer my own question, yes it does:
https://doc.rust-lang.org/nightly/nightly-rustc/rustc_target/spec/abi/enum.Abi.html

However, this enum seems a lot more like it's describing "calling convention" than "ABI".

similar to the fourth element of the platform's target triple. It often comes
after the `target_env` value. Embedded ABIs such as `gnueabihf` will define
`target_env` as `"gnu"` and `target_abi` as `"eabihf"`.

Example values:

- `""`
- `"abi64"`
- `"eabi"`
- `"eabihf"`
- `"macabi"`

# Drawbacks
[drawbacks]: #drawbacks

- Additional metadata for the compiler to keep track of.

- Like other `cfg`s, this can be manipulated at build time to be a value that
mismatches the actual target.

# Rationale and alternatives
[rationale-and-alternatives]: #rationale-and-alternatives

We can keep the existing work-around of checking the `TARGET` environment
variable in a `build.rs` script. However, this is not ideal because:

- Adding a build script increases compile time and makes a crate incompatible
with certain build systems.

- Checking `TARGET` is error prone, mainly because the ABI often follows
`target_env` without separation.

# Prior art
[prior-art]: #prior-art

- [Target component configurations][cfg-options]: `target_arch`,
`target_vendor`, `target_os`, and `target_env`.

- `CARGO_CFG_TARGET_*`
[environment variables for `build.rs`](https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts).

# Unresolved questions
[unresolved-questions]: #unresolved-questions

None.

# Future possibilities
[future-possibilities]: #future-possibilities

None.

[abi]: https://en.wikipedia.org/wiki/Application_binary_interface
[cfg-options]: https://doc.rust-lang.org/reference/conditional-compilation.html#set-configuration-options