-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
configuration
#2991
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
- Feature Name: `cfg-target` | ||
- Start Date: 2020-09-27 | ||
- RFC PR: [rust-lang/rfcs#2991](https://github.com/rust-lang/rfcs/pull/2991) | ||
- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000) | ||
|
||
# Summary | ||
[summary]: #summary | ||
|
||
This proposes a new `cfg`: `target`, which matches the entire target triple | ||
string (e.g. `arm-unknown-linux-gnueabihf`). This also adds a `CARGO_CFG_TARGET` | ||
environment variable for parity with other `CARGO_CFG_*` variables. | ||
|
||
# Motivation | ||
[motivation]: #motivation | ||
|
||
To `#[cfg]` against a specific target, a `build.rs` script is required to emit a | ||
custom `cfg` based on the `TARGET` environment variable. Adding a build script | ||
increases compile time and makes a crate incompatible with certain build | ||
systems. | ||
|
||
Otherwise, all available components would need to be specified separately: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I vaguely remember that the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Clang/LLVM treats empty components, We prefer the shortest spelling for convenience, but if Rust prefers always using normalized triples, we could switch to using |
||
`target_arch`, `target_vendor`, `target_os`, and `target_env`. This can be very | ||
cumbersome. Note that the target ABI cannot currently be `#[cfg]`-ed against, so | ||
a `build.rs` is still necessary to match all target components. | ||
|
||
# Guide-level explanation | ||
[guide-level-explanation]: #guide-level-explanation | ||
|
||
This would act like existing `target_*` configurations but match against all | ||
components (except `target_feature`). | ||
|
||
```rust | ||
#[cfg(target = "x86_64-apple-ios-macabi")] | ||
mod mac_catalyst; | ||
``` | ||
|
||
This includes `#[cfg_attr(target = "...", attr)]`. | ||
|
||
# Reference-level explanation | ||
[reference-level-explanation]: #reference-level-explanation | ||
|
||
`target` is a key-value option set once with the target's Rust triple. | ||
|
||
Example values: | ||
|
||
- `"aarch64-apple-darwin"` | ||
- `"arm-unknown-linux-gnueabihf"` | ||
- `"x86_64-apple-ios-macabi"` | ||
- `"x86_64-pc-windows-gnu"` | ||
- `"x86_64-pc-windows-msvc"` | ||
- `"x86_64-unknown-linux-gnu"` | ||
|
||
# Drawbacks | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Another drawback might be that technically this could be a breaking change with anybody that conditionally adds a This goes for your There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right, so if a person's build.rs had lines like say let target = env::var("TARGET").expect("Couldn't read `TARGET`");
println!("cargo:rustc-env=TARGET={}", target); Then technically they'd hit a small break ;P There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, that should be fine. The code would have to be: let target = env::var("TARGET").expect("Couldn't read `TARGET`");
println!("cargo:rustc-cfg=target={}", target); in order to have a break... Actually, this would define the target identically to what it was before, so they'd have to define it as something different (unless their definition would take priority?), or only in some cases, I guess. This is a problem adding any new predefined There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The string is equal to the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, that's what I meant by:
It might be a breaking change for: let target = env::var("CARGO_CFG_TARGET_ARCH").expect("Couldn't read `CARGO_CFG_TARGET_ARCH`");
println!("cargo:rustc-cfg=target={}", target); or if some_condition {
let target = env::var("TARGET").expect("Couldn't read `TARGET`");
println!("cargo:rustc-cfg=target={}", target);
} But these are pretty obscure cases... |
||
[drawbacks]: #drawbacks | ||
|
||
- Configuring against specific targets can be overly strict and could make | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the biggest drawback in my experience. People will often reach for the most accessible way to target a platform even if it's the wrong one. We saw this a lot in the Firefox codebase where people would use the |
||
certain `#[cfg]`s miss similar configurations with small changes. | ||
|
||
For example: `aarch64-unknown-none` does not match | ||
`aarch64-unknown-none-softfloat`, yet one would likely want to include ABI | ||
variants. The same concern applies to the target vendor. | ||
|
||
A potential solution would be to allow glob matching (e.g. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How feasible would it be to allow specifying individual components of the target triple string by keyword inside a #[cfg(target(arch="aarch64", os="none"))] which would be equivalent to: #[cfg(all(target_arch="aarch64", target_os="none"))] ? I definitely agree with the assertion that "matching the entire target with the current set of |
||
`aarch64-unknown-none*`), but that is not within the scope of this proposal | ||
because it is not currently used in other `#[cfg]`s. | ||
|
||
- The `CARGO_CFG_TARGET` environment variable is redundant with the existing | ||
`TARGET`. However, including it would be consistent with other `CARGO_CFG_*` | ||
variables. | ||
|
||
# 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, that increases compile time and makes | ||
a crate incompatible with certain build systems. | ||
|
||
# Prior art | ||
[prior-art]: #prior-art | ||
|
||
- [Target component configurations](https://doc.rust-lang.org/reference/conditional-compilation.html#set-configuration-options): | ||
`target_arch`, `target_vendor`, `target_os`, and `target_env`. | ||
|
||
- `TARGET` and `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 | ||
|
||
- How do we ensure a project does not miss configurations similar to the ones | ||
being `#[cfg]`-ed against with this feature? Perhaps this should be added as a | ||
Clippy lint that's off by default. | ||
|
||
# Future possibilities | ||
[future-possibilities]: #future-possibilities | ||
|
||
This would enable `#[cfg]`-ing against a specific target ABI (e.g. `macabi`, | ||
`eabihf`). However, that is not the motivation for this proposal and should be | ||
handled separately. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think the motivation section provides enough of a compelling argument for why this is desirable. Fleshing this out with specific examples of existing crates that use workarounds to achieve this and why they do so would be useful.