]>
Commit | Line | Data |
---|---|---|
9346a6ac AL |
1 | % Conditional Compilation |
2 | ||
bd371182 AL |
3 | Rust has a special attribute, `#[cfg]`, which allows you to compile code |
4 | based on a flag passed to the compiler. It has two forms: | |
5 | ||
6 | ```rust | |
7 | #[cfg(foo)] | |
8 | # fn foo() {} | |
9 | ||
10 | #[cfg(bar = "baz")] | |
11 | # fn bar() {} | |
12 | ``` | |
13 | ||
14 | They also have some helpers: | |
15 | ||
16 | ```rust | |
17 | #[cfg(any(unix, windows))] | |
18 | # fn foo() {} | |
19 | ||
20 | #[cfg(all(unix, target_pointer_width = "32"))] | |
21 | # fn bar() {} | |
22 | ||
23 | #[cfg(not(foo))] | |
24 | # fn not_foo() {} | |
25 | ``` | |
26 | ||
27 | These can nest arbitrarily: | |
28 | ||
29 | ```rust | |
30 | #[cfg(any(not(unix), all(target_os="macos", target_arch = "powerpc")))] | |
31 | # fn foo() {} | |
32 | ``` | |
33 | ||
34 | As for how to enable or disable these switches, if you’re using Cargo, | |
35 | they get set in the [`[features]` section][features] of your `Cargo.toml`: | |
36 | ||
62682a34 | 37 | [features]: http://doc.crates.io/manifest.html#the-%5Bfeatures%5D-section |
bd371182 AL |
38 | |
39 | ```toml | |
40 | [features] | |
41 | # no features by default | |
42 | default = [] | |
43 | ||
44 | # The “secure-password” feature depends on the bcrypt package. | |
45 | secure-password = ["bcrypt"] | |
46 | ``` | |
47 | ||
48 | When you do this, Cargo passes along a flag to `rustc`: | |
49 | ||
50 | ```text | |
51 | --cfg feature="${feature_name}" | |
52 | ``` | |
53 | ||
54 | The sum of these `cfg` flags will determine which ones get activated, and | |
55 | therefore, which code gets compiled. Let’s take this code: | |
56 | ||
57 | ```rust | |
58 | #[cfg(feature = "foo")] | |
59 | mod foo { | |
60 | } | |
61 | ``` | |
62 | ||
63 | If we compile it with `cargo build --features "foo"`, it will send the `--cfg | |
64 | feature="foo"` flag to `rustc`, and the output will have the `mod foo` in it. | |
65 | If we compile it with a regular `cargo build`, no extra flags get passed on, | |
66 | and so, no `foo` module will exist. | |
67 | ||
68 | # cfg_attr | |
69 | ||
70 | You can also set another attribute based on a `cfg` variable with `cfg_attr`: | |
71 | ||
72 | ```rust | |
73 | #[cfg_attr(a, b)] | |
74 | # fn foo() {} | |
75 | ``` | |
76 | ||
77 | Will be the same as `#[b]` if `a` is set by `cfg` attribute, and nothing otherwise. | |
78 | ||
79 | # cfg! | |
80 | ||
81 | The `cfg!` [syntax extension][compilerplugins] lets you use these kinds of flags | |
82 | elsewhere in your code, too: | |
83 | ||
84 | ```rust | |
85 | if cfg!(target_os = "macos") || cfg!(target_os = "ios") { | |
86 | println!("Think Different!"); | |
87 | } | |
88 | ``` | |
89 | ||
90 | [compilerplugins]: compiler-plugins.html | |
91 | ||
92 | These will be replaced by a `true` or `false` at compile-time, depending on the | |
93 | configuration settings. |