Include! macro invocation that expands into mod items

I’m trying to get my build.rs generate some Rust code that happens to include mod items without a body. As recommended in the Cargo docs, I do it with the include! macro. Here is a simplified case:

build.rs:

use std::env;
use std::fs::File;
use std::path::Path;
use std::io::Write;

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap();
    let out_path = Path::new(&out_dir).join("generated.rs");
    let mut f = File::create(out_path).unwrap();
    writeln!(f, "pub mod foo;").unwrap();
}

src/lib.rs:

include!(concat!(env!("OUT_DIR"), "/generated.rs"));

src/foo.rs:

pub fn foo() {
    println!("Hello, world");
}

However rustc complains, saying that it cannot find foo.rs. It looks like it looks for $OUT_DIR/foo.rs rather than lib/foo.rs. My questions:

  • Is this the intended behavior? i.e. if a mod foo; item is included into a Rust file, the foo module should be searched in the directory fo the included file, not the including file? The documentation on include! doesn’t seem very clear about this.
  • Is there an easy way to achieve what i wanted? i.e. making build.rs generate some code that contains mod foo;.