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