Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_platform/src/cfg.rs
6598 views
1
//! Provides helpful configuration macros, allowing detection of platform features such as
2
//! [`alloc`](crate::cfg::alloc) or [`std`](crate::cfg::std) without explicit features.
3
4
/// Provides a `match`-like expression similar to [`cfg_if`] and based on the experimental
5
/// [`cfg_match`].
6
/// The name `switch` is used to avoid conflict with the `match` keyword.
7
/// Arms are evaluated top to bottom, and an optional wildcard arm can be provided if no match
8
/// can be made.
9
///
10
/// An arm can either be:
11
/// - a `cfg(...)` pattern (e.g., `feature = "foo"`)
12
/// - a wildcard `_`
13
/// - an alias defined using [`define_alias`]
14
///
15
/// Common aliases are provided by [`cfg`](crate::cfg).
16
/// Note that aliases are evaluated from the context of the defining crate, not the consumer.
17
///
18
/// # Examples
19
///
20
/// ```
21
/// # use bevy_platform::cfg;
22
/// # fn log(_: &str) {}
23
/// # fn foo(_: &str) {}
24
/// #
25
/// cfg::switch! {
26
/// #[cfg(feature = "foo")] => {
27
/// foo("We have the `foo` feature!")
28
/// }
29
/// cfg::std => {
30
/// extern crate std;
31
/// std::println!("No `foo`, but we have `std`!");
32
/// }
33
/// _ => {
34
/// log("Don't have `std` or `foo`");
35
/// }
36
/// }
37
/// ```
38
///
39
/// [`cfg_if`]: https://crates.io/crates/cfg-if
40
/// [`cfg_match`]: https://github.com/rust-lang/rust/issues/115585
41
#[doc(inline)]
42
pub use crate::switch;
43
44
/// Defines an alias for a particular configuration.
45
/// This has two advantages over directly using `#[cfg(...)]`:
46
///
47
/// 1. Complex configurations can be abbreviated to more meaningful shorthand.
48
/// 2. Features are evaluated in the context of the _defining_ crate, not the consuming.
49
///
50
/// The second advantage is a particularly powerful tool, as it allows consuming crates to use
51
/// functionality in a defining crate regardless of what crate in the dependency graph enabled the
52
/// relevant feature.
53
///
54
/// For example, consider a crate `foo` that depends on another crate `bar`.
55
/// `bar` has a feature "`faster_algorithms`".
56
/// If `bar` defines a "`faster_algorithms`" alias:
57
///
58
/// ```ignore
59
/// define_alias! {
60
/// #[cfg(feature = "faster_algorithms")] => { faster_algorithms }
61
/// }
62
/// ```
63
///
64
/// Now, `foo` can gate its usage of those faster algorithms on the alias, avoiding the need to
65
/// expose its own "`faster_algorithms`" feature.
66
/// This also avoids the unfortunate situation where one crate activates "`faster_algorithms`" on
67
/// `bar` without activating that same feature on `foo`.
68
///
69
/// Once an alias is defined, there are 4 ways you can use it:
70
///
71
/// 1. Evaluate with no contents to return a `bool` indicating if the alias is active.
72
/// ```
73
/// # use bevy_platform::cfg;
74
/// if cfg::std!() {
75
/// // Have `std`!
76
/// } else {
77
/// // No `std`...
78
/// }
79
/// ```
80
/// 2. Pass a single code block which will only be compiled if the alias is active.
81
/// ```
82
/// # use bevy_platform::cfg;
83
/// cfg::std! {
84
/// // Have `std`!
85
/// # ()
86
/// }
87
/// ```
88
/// 3. Pass a single `if { ... } else { ... }` expression to conditionally compile either the first
89
/// or the second code block.
90
/// ```
91
/// # use bevy_platform::cfg;
92
/// cfg::std! {
93
/// if {
94
/// // Have `std`!
95
/// } else {
96
/// // No `std`...
97
/// }
98
/// }
99
/// ```
100
/// 4. Use in a [`switch`] arm for more complex conditional compilation.
101
/// ```
102
/// # use bevy_platform::cfg;
103
/// cfg::switch! {
104
/// cfg::std => {
105
/// // Have `std`!
106
/// }
107
/// cfg::alloc => {
108
/// // No `std`, but do have `alloc`!
109
/// }
110
/// _ => {
111
/// // No `std` or `alloc`...
112
/// }
113
/// }
114
/// ```
115
#[doc(inline)]
116
pub use crate::define_alias;
117
118
/// Macro which represents an enabled compilation condition.
119
#[doc(inline)]
120
pub use crate::enabled;
121
122
/// Macro which represents a disabled compilation condition.
123
#[doc(inline)]
124
pub use crate::disabled;
125
126
#[doc(hidden)]
127
#[macro_export]
128
macro_rules! switch {
129
({ $($tt:tt)* }) => {{
130
$crate::switch! { $($tt)* }
131
}};
132
(_ => { $($output:tt)* }) => {
133
$($output)*
134
};
135
(
136
$cond:path => $output:tt
137
$($( $rest:tt )+)?
138
) => {
139
$cond! {
140
if {
141
$crate::switch! { _ => $output }
142
} else {
143
$(
144
$crate::switch! { $($rest)+ }
145
)?
146
}
147
}
148
};
149
(
150
#[cfg($cfg:meta)] => $output:tt
151
$($( $rest:tt )+)?
152
) => {
153
#[cfg($cfg)]
154
$crate::switch! { _ => $output }
155
$(
156
#[cfg(not($cfg))]
157
$crate::switch! { $($rest)+ }
158
)?
159
};
160
}
161
162
#[doc(hidden)]
163
#[macro_export]
164
macro_rules! disabled {
165
() => { false };
166
(if { $($p:tt)* } else { $($n:tt)* }) => { $($n)* };
167
($($p:tt)*) => {};
168
}
169
170
#[doc(hidden)]
171
#[macro_export]
172
macro_rules! enabled {
173
() => { true };
174
(if { $($p:tt)* } else { $($n:tt)* }) => { $($p)* };
175
($($p:tt)*) => { $($p)* };
176
}
177
178
#[doc(hidden)]
179
#[macro_export]
180
macro_rules! define_alias {
181
(
182
#[cfg($meta:meta)] => $p:ident
183
$(, $( $rest:tt )+)?
184
) => {
185
$crate::define_alias! {
186
#[cfg($meta)] => { $p }
187
$(
188
$($rest)+
189
)?
190
}
191
};
192
(
193
#[cfg($meta:meta)] => $p:ident,
194
$($( $rest:tt )+)?
195
) => {
196
$crate::define_alias! {
197
#[cfg($meta)] => { $p }
198
$(
199
$($rest)+
200
)?
201
}
202
};
203
(
204
#[cfg($meta:meta)] => {
205
$(#[$p_meta:meta])*
206
$p:ident
207
}
208
$($( $rest:tt )+)?
209
) => {
210
$crate::switch! {
211
#[cfg($meta)] => {
212
$(#[$p_meta])*
213
#[doc(inline)]
214
///
215
#[doc = concat!("This macro passes the provided code because `#[cfg(", stringify!($meta), ")]` is currently active.")]
216
pub use $crate::enabled as $p;
217
}
218
_ => {
219
$(#[$p_meta])*
220
#[doc(inline)]
221
///
222
#[doc = concat!("This macro suppresses the provided code because `#[cfg(", stringify!($meta), ")]` is _not_ currently active.")]
223
pub use $crate::disabled as $p;
224
}
225
}
226
227
$(
228
$crate::define_alias! {
229
$($rest)+
230
}
231
)?
232
}
233
}
234
235
define_alias! {
236
#[cfg(feature = "alloc")] => {
237
/// Indicates the `alloc` crate is available and can be used.
238
alloc
239
}
240
#[cfg(feature = "std")] => {
241
/// Indicates the `std` crate is available and can be used.
242
std
243
}
244
#[cfg(panic = "unwind")] => {
245
/// Indicates that a [`panic`] will be unwound, and can be potentially caught.
246
panic_unwind
247
}
248
#[cfg(panic = "abort")] => {
249
/// Indicates that a [`panic`] will lead to an abort, and cannot be caught.
250
panic_abort
251
}
252
#[cfg(all(target_arch = "wasm32", feature = "web"))] => {
253
/// Indicates that this target has access to browser APIs.
254
web
255
}
256
#[cfg(all(feature = "alloc", target_has_atomic = "ptr"))] => {
257
/// Indicates that this target has access to a native implementation of `Arc`.
258
arc
259
}
260
#[cfg(feature = "critical-section")] => {
261
/// Indicates `critical-section` is available.
262
critical_section
263
}
264
}
265
266