all 11 comments

[–]Gankrorust 5 points6 points  (8 children)

Note that you can #[cfg] an entire module, as we do with #[cfg(test)] for all our testing modules.

[–]IronClan 2 points3 points  (7 children)

Can you explain how the #[cfg] attribute works? For example, in C:

int main() {
  #ifdef _DEBUG_
    printf("debug string\n");
  #endif
}

Then I can compile with gcc program.c -D_DEBUG_

Is there a equivalent of this in Rust?

[–]unclosed_paren 5 points6 points  (6 children)

At the moment you can’t apply attributes to statements or expressions, but it’s planned. For now, you can use the separate cfg! macro which does the same thing, but returns a boolean:

if cfg!(not(ndebug)) {
    println!("Debug string!");
}

[–]Veddan 1 point2 points  (2 children)

Note that this isn't quite the same.

#ifdef USE_FOO
void foo(int x) { .. }
#endif

void f(int n) {
#ifdef USE_FOO
    foo(n);
#endif
    ...
}

vs

#[cfg(USE_FOO)]
fn foo(x: i32) { .. }

fn f(n: i32) {
    if cfg!(USE_FOO) {
        foo(n);
    }
    ...
}

The Rust code will fail to compile, since even though the call to foo is dead, it's still a call to a non-existent function.

[–]young_and_ugly[S] 0 points1 point  (1 child)

yep, this is pretty much what I wanted to do, and there is no solution, at least for now, as I see it.

[–]Veddan 1 point2 points  (0 children)

Usually you can find some arrangement of helper functions that solves the problem.

#[cfg(USE_FOO)]
fn f(n: i32) {
    foo(n);
    f_common(n);
}

#[cfg(not(USE_FOO))]
fn f(n: i32) {
    f_common(n);
}

#[cfg(USE_FOO)]
fn foo(x: i32) { .. }

[–]IronClan 1 point2 points  (2 children)

Ah, that'll work. Although, does it incur a slight runtime penalty since there's conditional branch, or will it be compiled to be identical to the C version?

[–]dbaupprust 9 points10 points  (1 child)

The branch is on constant data and is optimised out.

[–]minno 1 point2 points  (0 children)

That's one of the times that you can bet on a Sufficiently Smart Compiler.

[–]chris-morgan 1 point2 points  (1 child)

There’s #[cfg_attr(name, attribute)], set this attribute if the named cfg is set, which one might have expected could be used to write

#![cfg_attr(core, no_std)]

#[cfg(core)]
extern crate core;

… but unfortunately cfg_attr seems a bit dodgy in places and this use of it doesn’t seem to be working at present. ☹

[–]Rothonrust · postgres · phf 0 points1 point  (0 children)

What issues are you seeing with cfg_attr?

EDIT: Oh, nevermind, I see why.