How can I import a source file from my library into build.rs?

Viewed 942

I have the following file structure:

src/
    lib.rs
    foo.rs
build.rs

I would like to import something from foo.rs (lib.rs has pub mod foo in it already) into build.rs. (I'm trying to import a type in order to generate some JSON schema at build time)

Is this possible?

1 Answers

You cannot cleanly — the build script is used to build the library, so by definition must run before the library is built.

Clean solution

Put the type into another library and import the new library into both the build script and your original library

.
├── the_library
│   ├── Cargo.toml
│   ├── build.rs
│   └── src
│       └── lib.rs
└── the_type
    ├── Cargo.toml
    └── src
        └── lib.rs

the_type/src/lib.rs

pub struct TheCoolType;

the_library/Cargo.toml

# ...

[dependencies]
the_type = { path = "../the_type" }

[build-dependencies]
the_type = { path = "../the_type" }

the_library/build.rs

fn main() {
    the_type::TheCoolType;
}

the_library/src/lib.rs

pub fn thing() {
    the_type::TheCoolType;
}

Hacky solution

Use something like #[path] mod ... or include! to include the code twice. This is basically pure textual substitution, so it's very brittle.

.
├── Cargo.toml
├── build.rs
└── src
    ├── foo.rs
    └── lib.rs

build.rs

// One **exactly one** of this...
#[path = "src/foo.rs"]
mod foo;

// ... or this
// mod foo {
//     include!("src/foo.rs");
// }

fn main() {
    foo::TheCoolType;
}

src/lib.rs

mod foo;

pub fn thing() {
    foo::TheCoolType;
}

src/foo.rs

pub struct TheCoolType;
Related