Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to build a binary and a library with the same configuration options?

As of the time of asking, if you have a bin and a lib in the same cargo project and would like to build the bin and lib with specific rustc cfg options it doesn't work.

You can build one or the other with rustc cfg options, but not both. And if you try and build the lib then the bin when the bin is compiled it recompiled the lib without the rustc options.

Is there a way to do both and if not why? Am I doomed to have to create my own build script anyways? If so, what's the point of having cargo?

EDIT

ok so maybe i was being a little dramatic

Background/Expansion

Say I had something like:

src/lib.rs

pub mod mylib {

    #[cfg(not(dosomething))]
    pub use self::without_cfg::dosomething;

    #[cfg(dosomething)]
    pub use self::with_cfg::dosomething;


    mod with_cfg {
        pub fn dosomething() {
            println!("config option");
        }
    }

    mod without_cfg {
        pub fn dosomething() {
            println!("no config option");
        }
    }

} 

src/main.rs

extern crate modules;

use modules::mylib::dosomething;

fn main() {
    dosomething();
}

So that if I compiled with the cfg option of dosomething I would get one version of a function, but if I didn't have the config I would get the "default" behavior or whatever.

Now if I try and compile with cargo rustc I can never get a version of the bin with the cfg dosomething set in the lib.

The closest I've come to being able to do it all in cargo is:

cargo rustc -v --lib -- --cfg dosomething
cargo rustc -v --bin [bin name] -- --cfg dosomething

which the first command will compile the lib with the cfg but the second command with recompile the lib without the cfg in order to create the bin.

the only workaround I've come up with is to:

cargo rustc -v --bin [bin name] -- --cfg dosomething

copy what it spits out for the command to compile such as:

rustc src/main.rs --crate-name [bin name] --crate-type bin -g --cfg dosomething --out-dir [/path/to/project]/target/debug --emit=dep-info,link -L dependency=[/path/to/project]/target/debug -L dependency=[/path/to/project]/target/debug/deps --extern modules=[/path/to/project]/target/debug/libmodules.rlib`

then run:

cargo rustc -v --lib -- --cfg dosomething

and finally copy and paste the rustc command from earlier in order to compile the bin with the lib having the cfg option set.

Is that the only way? Why can't I somehow specify which libs/bins get the rustc cfg options I want, even if its in the Cargo.toml? Or can I and I don't realize it?

For those that asked...

Cargo.toml:

[package]
name = "[bin name]"
version = "0.1.0"
authors = ["[Me] <[my email]>"]

[lib]
name = "modules"
path = "src/lib.rs"

P.S. Thank you to all those who have worked on rust and cargo, all in all I find it a pleasant environment to work in and LOVE the language. Keep up the good work.

like image 582
sbditto85 Avatar asked May 23 '15 16:05

sbditto85


Video Answer


1 Answers

If I understand you correctly, then Cargos features should help out here:

src/lib.rs

#[cfg(feature = "dosomething")]
pub use self::with_cfg::dosomething;

#[cfg(not(feature = "dosomething"))]
pub use self::without_cfg::dosomething;

#[cfg(feature = "dosomething")]
mod with_cfg {
    pub fn dosomething() {
        println!("config option");
    }
}

#[cfg(not(feature = "dosomething"))]
mod without_cfg {
    pub fn dosomething() {
        println!("no config option");
    }
}

src/main.rs

extern crate what;

use what::dosomething;

fn main() {
    dosomething();
}

Cargo.toml

[package]
name = "what"
version = "0.1.0"
authors = ["An Devloper <[email protected]>"]

[features]
dosomething = []

Now, when I can compile or run in either mode:

$ cargo run
   Compiling what v0.1.0 (file:///private/tmp/what)
     Running `target/debug/what`
no config option

$ cargo run --features dosomething
   Compiling what v0.1.0 (file:///private/tmp/what)
     Running `target/debug/what`
config option
like image 189
Shepmaster Avatar answered Dec 10 '22 05:12

Shepmaster