1# Conditional compilation 2 3> **<sup>Syntax</sup>**\ 4> _ConfigurationPredicate_ :\ 5> _ConfigurationOption_\ 6> | _ConfigurationAll_\ 7> | _ConfigurationAny_\ 8> | _ConfigurationNot_ 9> 10> _ConfigurationOption_ :\ 11> [IDENTIFIER] (`=` ([STRING_LITERAL] | [RAW_STRING_LITERAL]))<sup>?</sup> 12> 13> _ConfigurationAll_\ 14> `all` `(` _ConfigurationPredicateList_<sup>?</sup> `)` 15> 16> _ConfigurationAny_\ 17> `any` `(` _ConfigurationPredicateList_<sup>?</sup> `)` 18> 19> _ConfigurationNot_\ 20> `not` `(` _ConfigurationPredicate_ `)` 21> 22> _ConfigurationPredicateList_\ 23> _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> `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> `cfg_attr` `(` _ConfigurationPredicate_ `,` _CfgAttrs_<sup>?</sup> `)` 265> 266> _CfgAttrs_ :\ 267> [_Attr_] (`,` [_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