Skip to content

Commit

Permalink
TRPL: attributes & conditional compilation
Browse files Browse the repository at this point in the history
  • Loading branch information
steveklabnik committed Apr 22, 2015
1 parent 3860240 commit a5ae4cc
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 3 deletions.
2 changes: 1 addition & 1 deletion src/doc/trpl/SUMMARY.md
Expand Up @@ -9,6 +9,7 @@
* [The Stack and the Heap](the-stack-and-the-heap.md)
* [Debug and Display](debug-and-display.md)
* [Testing](testing.md)
* [Conditional Compilation](conditional-compilation.md)
* [Documentation](documentation.md)
* [Iterators](iterators.md)
* [Concurrency](concurrency.md)
Expand Down Expand Up @@ -47,7 +48,6 @@
* [`const`](const.md)
* [Tuple Structs](tuple-structs.md)
* [Attributes](attributes.md)
* [Conditional Compilation](conditional-compilation.md)
* [`type` aliases](type-aliases.md)
* [Casting between types](casting-between-types.md)
* [Associated Types](associated-types.md)
Expand Down
69 changes: 68 additions & 1 deletion src/doc/trpl/attributes.md
@@ -1,3 +1,70 @@
% Attributes

Coming Soon!
Declarations can be annotated with ‘attributes’ in Rust. They look like this:

```rust
#[test]
# fn foo() {}
```

or like this:

```rust
# mod foo {
#![test]
# }
```

The difference between the two is the `!`, which changes what the attribute
applies to:

```rust,ignore
#[foo]
struct Foo;
mod bar {
#![bar]
}
```

The `#[foo]` attribute applies to the next item, which is the `struct`
declaration. The `#![bar]` attribute applies to the item enclosing it, which is
the `mod` declaration. Otherwise, they’re the same. Both change the meaning of
the item they’re attached to somehow.

For example, consider a function like this:

```rust
#[test]
fn check() {
assert_eq!(2, 1 + 1);
}
```

It is marked with `#[test]`. This means it’s special: when you run
[tests][tests], this function will execute. When you compile as usual, it won’t
even be included. This function is now a test function.

[tests]: testing.html

Attributes may also have additional data:

```rust
#[inline(always)]
fn super_fast_fn() {
# }
```

Or even keys and values:

```rust
#[cfg(target_os = "macos")]
mod macos_only {
# }
```

Rust attributes are used for a number of different things. There is a full list
of attributes [in the reference][reference]. Currently, you are not allowed to
create your own attributes, the Rust compiler defines them.

[reference]: reference.html#attributes
92 changes: 91 additions & 1 deletion src/doc/trpl/conditional-compilation.md
@@ -1,3 +1,93 @@
% Conditional Compilation

Coming Soon!
Rust has a special attribute, `#[cfg]`, which allows you to compile code
based on a flag passed to the compiler. It has two forms:

```rust
#[cfg(foo)]
# fn foo() {}

#[cfg(bar = "baz")]
# fn bar() {}
```

They also have some helpers:

```rust
#[cfg(any(unix, windows))]
# fn foo() {}

#[cfg(all(unix, target_pointer_width = "32"))]
# fn bar() {}

#[cfg(not(foo))]
# fn not_foo() {}
```

These can nest arbitrarily:

```rust
#[cfg(any(not(unix), all(target_os="macos", target_arch = "powerpc")))]
# fn foo() {}
```

As for how to enable or disable these switches, if you’re using Cargo,
they get set in the [`[features]` section][features] of your `Cargo.toml`:

[features]: http://doc.crates.io/manifest.html#the-[features]-section

```toml
[features]
# no features by default
default = []

# The “secure-password” feature depends on the bcrypt package.
secure-password = ["bcrypt"]
```

When you do this, Cargo passes along a flag to `rustc`:

```
--cfg feature="${feature_name}"
```

The sum of these `cfg` flags will determine which ones get activated, and
therefore, which code gets compiled. Let’s take this code:

```rust
#[cfg(feature = "foo")]
mod foo {
}
```

If we compile it with `cargo build --features "foo"`, it will send the `--cfg
feature="foo"` flag to `rustc`, and the output will have the `mod foo` in it.
If we compile it with a regular `cargo build`, no extra flags get passed on,
and so, no `foo` module will exist.

# cfg_attr

You can also set another attribute based on a `cfg` variable with `cfg_attr`:

```rust
#[cfg_attr(a, b)]
# fn foo() {}
```

Will be the same as `#[b]` if `a` is set by `cfg` attribute, and nothing otherwise.

# cfg!

The `cfg!` [syntax extension][compilerplugins] lets you use these kinds of flags
elsewhere in your code, too:

```rust
if cfg!(target_os = "macos") || cfg!(target_os = "ios") {
println!("Think Different!");
}
```

[compilerplugins]: compiler-plugins.html

These will be replaced by a `true` or `false` at compile-time, depending on the
configuration settings.

0 comments on commit a5ae4cc

Please sign in to comment.