Conditional Compilation for include from build.rs

Is there a way to detect if the file is included from build.rs or included normally?
I have the following files:

build.rs
  cli.rs
  calendar.rs

I include cli.rs in build.rs, but cli.rs is using calendar.rs:

cli.rs:

use crate::calendar::Timer;

build.rs:

include!("src/calendar.rs");
include!("src/cli.rs");

Is this possible? I thought about disabling the use statement with a cfg but not sure how to detect that it is included from the build.rs.

You can emit a rustc-cfg instruction from the build script.

Alternatively you could just make the paths be the same in either case.

#[path = "src/calendar.rs"]
mod calendar;

Thanks, the rust-cfg worked.

I couldn't get #[path=calendar.rs" to work, because I include a trait from calendar in my main.rs and that was then not compatible with the type included in cli.

Huh, I'm not sure I understand exactly what problem you ran into?

My mistake was defining module twice, I read the cargo log carefully and found that I need to include the trait via cli to work:

use crate::cli::calendar::TimerAble;

Below what I did before and expected to work (timer is a function of TimerAble):

In cli.rs I have a struct:

#[path = "calendar.rs"]
mod calendar;
use calendar::{Timer}
#[derive(Debug, Clap)]
pub enum Target {
    When {
        timer: Timer,
    }
}

And I use it in main.rs

#[path = "calendar.rs"]
mod calendar;
use calendar::TimerAble;
fn timer(target: cli::Target) -> Option<String> {
    match target {
        Target::When { timer  } => Some(timer.timer())
    }
}

Ah, right.

mod calendar;

is equivalent to

mod calendar {
    contents of calendar.rs go here
}

So if you have two mod calendar statements, that's equivalent to copy-pasting the contents of the file twice, resulting in everything inside it being defined twice.

1 Like