1# Conditional compilation
2
3> **<sup>Syntax</sup>**\
4> _ConfigurationPredicate_ :\
5> &nbsp;&nbsp; &nbsp;&nbsp; _ConfigurationOption_\
6> &nbsp;&nbsp; | _ConfigurationAll_\
7> &nbsp;&nbsp; | _ConfigurationAny_\
8> &nbsp;&nbsp; | _ConfigurationNot_
9>
10> _ConfigurationOption_ :\
11> &nbsp;&nbsp; [IDENTIFIER]&nbsp;(`=` ([STRING_LITERAL] | [RAW_STRING_LITERAL]))<sup>?</sup>
12>
13> _ConfigurationAll_\
14> &nbsp;&nbsp; `all` `(` _ConfigurationPredicateList_<sup>?</sup> `)`
15>
16> _ConfigurationAny_\
17> &nbsp;&nbsp; `any` `(` _ConfigurationPredicateList_<sup>?</sup> `)`
18>
19> _ConfigurationNot_\
20> &nbsp;&nbsp; `not` `(` _ConfigurationPredicate_ `)`
21>
22> _ConfigurationPredicateList_\
23> &nbsp;&nbsp; _ConfigurationPredicate_ (`,` _ConfigurationPredicate_)<sup>\*</sup> `,`<sup>?</sup>
24
25*Conditionally compiled source code* is source code that may or may not be
26considered a part of the source code depending on certain conditions. <!-- This
27definition is sort of vacuous --> Source code can be conditionally compiled
28using the [attributes] [`cfg`] and [`cfg_attr`] and the built-in [`cfg` macro].
29These conditions are based on the target architecture of the compiled crate,
30arbitrary values passed to the compiler, and a few other miscellaneous things
31further described below in detail.
32
33Each form of conditional compilation takes a _configuration predicate_ that
34evaluates to true or false. The predicate is one of the following:
35
36* A configuration option. It is true if the option is set and false if it is
37  unset.
38* `all()` with a comma separated list of configuration predicates. It is false
39  if at least one predicate is false. If there are no predicates, it is true.
40* `any()` with a comma separated list of configuration predicates. It is true
41  if at least one predicate is true. If there are no predicates, it is false.
42* `not()` with a configuration predicate. It is true if its predicate is false
43  and false if its predicate is true.
44
45_Configuration options_ are names and key-value pairs that are either set or
46unset. Names are written as a single identifier such as, for example, `unix`.
47Key-value pairs are written as an identifier, `=`, and then a string. For
48example, `target_arch = "x86_64"` is a configuration option.
49
50> **Note**: Whitespace around the `=` is ignored. `foo="bar"` and `foo = "bar"`
51> are equivalent configuration options.
52
53Keys are not unique in the set of key-value configuration options. For example,
54both `feature = "std"` and `feature = "serde"` can be set at the same time.
55
56## Set Configuration Options
57
58Which configuration options are set is determined statically during the
59compilation of the crate. Certain options are _compiler-set_ based on data
60about the compilation. Other options are _arbitrarily-set_, set based on input
61passed to the compiler outside of the code. It is not possible to set a
62configuration option from within the source code of the crate being compiled.
63
64> **Note**: For `rustc`, arbitrary-set configuration options are set using the
65> [`--cfg`] flag.
66
67> **Note**: Configuration options with the key `feature` are a convention used
68> by [Cargo][cargo-feature] for specifying compile-time options and optional
69> dependencies.
70
71<div class="warning">
72
73Warning: It is possible for arbitrarily-set configuration options to have the
74same value as compiler-set configuration options. For example, it is possible
75to do `rustc --cfg "unix" program.rs` while compiling to a Windows target, and
76have both `unix` and `windows` configuration options set at the same time. It
77is unwise to actually do this.
78
79</div>
80
81### `target_arch`
82
83Key-value option set once with the target's CPU architecture. The value is
84similar to the first element of the platform's target triple, but not
85identical.
86
87Example values:
88
89* `"x86"`
90* `"x86_64"`
91* `"mips"`
92* `"powerpc"`
93* `"powerpc64"`
94* `"arm"`
95* `"aarch64"`
96
97### `target_feature`
98
99Key-value option set for each platform feature available for the current
100compilation target.
101
102Example values:
103
104* `"avx"`
105* `"avx2"`
106* `"crt-static"`
107* `"rdrand"`
108* `"sse"`
109* `"sse2"`
110* `"sse4.1"`
111
112See the [`target_feature` attribute] for more details on the available
113features. An additional feature of `crt-static` is available to the
114`target_feature` option to indicate that a [static C runtime] is available.
115
116### `target_os`
117
118Key-value option set once with the target's operating system. This value is
119similar to the second and third element of the platform's target triple.
120
121Example values:
122
123* `"windows"`
124* `"macos"`
125* `"ios"`
126* `"linux"`
127* `"android"`
128* `"freebsd"`
129* `"dragonfly"`
130* `"openbsd"`
131* `"netbsd"`
132
133### `target_family`
134
135Key-value option providing a more generic description of a target, such as the family of the
136operating systems or architectures that the target generally falls into. Any number of
137`target_family` key-value pairs can be set.
138
139Example values:
140
141* `"unix"`
142* `"windows"`
143* `"wasm"`
144
145### `unix` and `windows`
146
147`unix` is set if `target_family = "unix"` is set and `windows` is set if
148`target_family = "windows"` is set.
149
150### `target_env`
151
152Key-value option set with further disambiguating information about the target
153platform with information about the ABI or `libc` used. For historical reasons,
154this value is only defined as not the empty-string when actually needed for
155disambiguation. Thus, for example, on many GNU platforms, this value will be
156empty. This value is similar to the fourth element of the platform's target
157triple. One difference is that embedded ABIs such as `gnueabihf` will simply
158define `target_env` as `"gnu"`.
159
160Example values:
161
162* `""`
163* `"gnu"`
164* `"msvc"`
165* `"musl"`
166* `"sgx"`
167
168### `target_endian`
169
170Key-value option set once with either a value of "little" or "big" depending
171on the endianness of the target's CPU.
172
173### `target_pointer_width`
174
175Key-value option set once with the target's pointer width in bits.
176
177Example values:
178
179* `"16"`
180* `"32"`
181* `"64"`
182
183### `target_vendor`
184
185Key-value option set once with the vendor of the target.
186
187Example values:
188
189* `"apple"`
190* `"fortanix"`
191* `"pc"`
192* `"unknown"`
193
194### `test`
195
196Enabled when compiling the test harness. Done with `rustc` by using the
197[`--test`] flag. See [Testing] for more on testing support.
198
199### `debug_assertions`
200
201Enabled by default when compiling without optimizations.
202This can be used to enable extra debugging code in development but not in
203production.  For example, it controls the behavior of the standard library's
204[`debug_assert!`] macro.
205
206### `proc_macro`
207
208Set when the crate being compiled is being compiled with the `proc_macro`
209[crate type].
210
211## Forms of conditional compilation
212
213### The `cfg` attribute
214
215> **<sup>Syntax</sup>**\
216> _CfgAttrAttribute_ :\
217> &nbsp;&nbsp; `cfg` `(` _ConfigurationPredicate_ `)`
218
219<!-- should we say they're active attributes here? -->
220
221The `cfg` [attribute] conditionally includes the thing it is attached to based
222on a configuration predicate.
223
224It is written as `cfg`, `(`, a configuration predicate, and finally `)`.
225
226If the predicate is true, the thing is rewritten to not have the `cfg` attribute
227on it. If the predicate is false, the thing is removed from the source code.
228
229Some examples on functions:
230
231```rust
232// The function is only included in the build when compiling for macOS
233#[cfg(target_os = "macos")]
234fn macos_only() {
235  // ...
236}
237
238// This function is only included when either foo or bar is defined
239#[cfg(any(foo, bar))]
240fn needs_foo_or_bar() {
241  // ...
242}
243
244// This function is only included when compiling for a unixish OS with a 32-bit
245// architecture
246#[cfg(all(unix, target_pointer_width = "32"))]
247fn on_32bit_unix() {
248  // ...
249}
250
251// This function is only included when foo is not defined
252#[cfg(not(foo))]
253fn needs_not_foo() {
254  // ...
255}
256```
257
258The `cfg` attribute is allowed anywhere attributes are allowed.
259
260### The `cfg_attr` attribute
261
262> **<sup>Syntax</sup>**\
263> _CfgAttrAttribute_ :\
264> &nbsp;&nbsp; `cfg_attr` `(` _ConfigurationPredicate_ `,` _CfgAttrs_<sup>?</sup> `)`
265>
266> _CfgAttrs_ :\
267> &nbsp;&nbsp; [_Attr_]&nbsp;(`,` [_Attr_])<sup>\*</sup> `,`<sup>?</sup>
268
269The `cfg_attr` [attribute] conditionally includes [attributes] based on a
270configuration predicate.
271
272When the configuration predicate is true, this attribute expands out to the
273attributes listed after the predicate. For example, the following module will
274either be found at `linux.rs` or `windows.rs` based on the target.
275
276<!-- ignore: `mod` needs multiple files -->
277```rust,ignore
278#[cfg_attr(target_os = "linux", path = "linux.rs")]
279#[cfg_attr(windows, path = "windows.rs")]
280mod os;
281```
282
283Zero, one, or more attributes may be listed. Multiple attributes will each be
284expanded into separate attributes. For example:
285
286<!-- ignore: fake attributes -->
287```rust,ignore
288#[cfg_attr(feature = "magic", sparkles, crackles)]
289fn bewitched() {}
290
291// When the `magic` feature flag is enabled, the above will expand to:
292#[sparkles]
293#[crackles]
294fn bewitched() {}
295```
296
297> **Note**: The `cfg_attr` can expand to another `cfg_attr`. For example,
298> `#[cfg_attr(target_os = "linux", cfg_attr(feature = "multithreaded", some_other_attribute))]`
299> is valid. This example would be equivalent to
300> `#[cfg_attr(all(target_os = "linux", feature ="multithreaded"), some_other_attribute)]`.
301
302The `cfg_attr` attribute is allowed anywhere attributes are allowed.
303
304### The `cfg` macro
305
306The built-in `cfg` macro takes in a single configuration predicate and evaluates
307to the `true` literal when the predicate is true and the `false` literal when
308it is false.
309
310For example:
311
312```rust
313let machine_kind = if cfg!(unix) {
314  "unix"
315} else if cfg!(windows) {
316  "windows"
317} else {
318  "unknown"
319};
320
321println!("I'm running on a {} machine!", machine_kind);
322```
323
324[IDENTIFIER]: identifiers.md
325[RAW_STRING_LITERAL]: tokens.md#raw-string-literals
326[STRING_LITERAL]: tokens.md#string-literals
327[Testing]: attributes/testing.md
328[_Attr_]: attributes.md
329[`--cfg`]: ../rustc/command-line-arguments.html#--cfg-configure-the-compilation-environment
330[`--test`]: ../rustc/command-line-arguments.html#--test-build-a-test-harness
331[`cfg`]: #the-cfg-attribute
332[`cfg` macro]: #the-cfg-macro
333[`cfg_attr`]: #the-cfg_attr-attribute
334[`debug_assert!`]: ../std/macro.debug_assert.html
335[`target_feature` attribute]: attributes/codegen.md#the-target_feature-attribute
336[attribute]: attributes.md
337[attributes]: attributes.md
338[cargo-feature]: ../cargo/reference/features.html
339[crate type]: linkage.md
340[static C runtime]: linkage.md#static-and-dynamic-c-runtimes
341