dying_sphynx
dying_sphynx

Reputation: 1166

Using conditionally compiled module under `cfg` macro

I wonder how to use a conditionally compiled module under cfg! macro. I am trying this:

pub fn f() { ... }

#[cfg(feature = "x")]
pub mod xmodule {
   pub fn f() { ... }
}

pub fn test() {
  if cfg!(feature = "x") {
    xmodule::f();
  } else {
    f();
  }; 
}

It works fine when I compile it with cargo check --features x, but if I don't enable the feature it fails with the following error:

use of undeclared type or module `xmodule`

Am I doing something wrong or the compilation is not smart enough to understand that the module should not be used if the feature is not set?

Upvotes: 2

Views: 1828

Answers (1)

Freyja
Freyja

Reputation: 40884

While the #[cfg] attribute will conditionally compile code, cfg! is gives the equivalent boolean value (e.g. true if a feature is enabled, false otherwise). So your code essentially compiles into:

pub fn test() {
  if false { // assuming "x" feature is not set
    xmodule::f();
  } else {
    f();
  }; 
}

Therefore both branches must still contain valid code, even if only one is ever run.

To get actual conditional compilation, you may do something like this:

pub fn test() {
  #[cfg(feature = "x")]
  fn inner() {
    xmodule::f()
  }

  #[cfg(not(feature = "x"))]
  fn inner() {
    f()
  }

  inner();
}

Playground example

Or you can use a third-party macro like cfg-if:

use cfg_if::cfg_if;

pub fn test() {
  cfg_if! {
    if #[cfg(feature = "x")] {
      xmodule::f();
    } else {
      f();
    }
  }
}

Playground example

Upvotes: 6

Related Questions