- Feature Name:
cfg-target
- Start Date: 2020-09-27
- RFC PR: rust-lang/rfcs#3239
- Rust Issue: rust-lang/rust#96901
This RFC was previously approved, but part of it later withdrawn
The cfg(target = "...")
conditional compilation key was previously approved,
but was later withdrawn. For details, see the summary comment.
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.
In addition, this proposes a shorthand cfg(target(...))
to match multiple
components of a target string at once.
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:
target_arch
, target_vendor
, target_os
, target_env
and target_abi
.
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
This would act like existing target_*
configurations (except target_feature
)
but match against all components.
#[cfg(target = "x86_64-apple-ios-macabi")]
mod mac_catalyst;
This includes #[cfg_attr(target = "...", attr)]
.
It would also support to specify each target_*
inside a new target
attribute as follows:
// So we can for example rewrite:
#[cfg(all(target_os = "linux", target_arch = "arm"))]
// as:
#[cfg(target(os = "linux", arch = "arm"))]
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"
Semantics of target with attributes
The shorthand form of #[cfg(target(os = "linux))]
is expanded and entirely
equivalent to #[cfg(target_os = "linux")]
(and so on for arch
and the other
potential attributes).
Drawbacks
-
Configuring against specific targets can be overly strict and could make certain
#[cfg]
s miss similar configurations with small changes.For example:
aarch64-unknown-none
does not matchaarch64-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.
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 existingTARGET
. However, including it would be consistent with otherCARGO_CFG_*
variables.
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
-
Target component configurations:
target_arch
,target_vendor
,target_os
, andtarget_env
. -
TARGET
andCARGO_CFG_TARGET_*
environment variables forbuild.rs
.
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
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.