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