Conditionally compiling code if a dependency exists


#1

Is there a way to conditionally compile code if an optional dependency is used by another library/binary? For example, I have a an Error type that implements various From and Into traits. If the iron web framework is being used I’d like to add another Into trait to convert my error type into iron’s error type.


#2

cfg - for conditional compilation
cfg! macro - to conditionally select code blocks(not sure if I express myself correctly here).
cargo’s features - for conditionally configuring the build process, can also export variables for #[cfg].


#3

I see you probably checked cfg, you also need cargo's features.

From the limited knowledge of your setup, that’s how it could look:
Cargo.toml:

[features]
use-iron = ["iron"]

[dependencies]
rayon  = "^0.3"
diesel = "^0.5"

iron = { version = "^0.3", optional = true }

code.rs:

#[cfg(feature = "use-iron")]
fn some_func() -> ! { panic!("Not implemented!") }

Terminal:

cargo build --features "use-iron"

#4

@LilianMoraru So there is no way to intelligently detect if a dependency is in the environment?


#5

By environment you mean a library installed on the system?
Usually Rust projects define their dependencies into Cargo.toml and that’s how the libraries are linked, instead of linking system libraries.

But of course, if you use cargo’s build script you can do anything… If you want, you can pull settings from the network this way :slight_smile:


#6

By environment I guess I actually mean the Rust dependency tree. So instead of using feature flags I’d like to be able to tell if another crate in the dependency tree depends on iron.


#7

It is definitely possible but I have to think if it is possible to avoid the build script(because it’s more complicated than setting fields in Cargo.toml)


#8

Well, what you want is deeper knowledge of the dependency graph, this seems to not be possible without code logic…
May be someone else has a better idea but I think you will have to use a cargo's build script and may be tap into cargo’s API, or it might be that you don’t have to use the API, not sure if links manifest key can help with that…
Build script scanning Cargo.lock? Bad idea?

I am pretty sure you need to use the build script but what feature set to use from it, not sure. It is powerful, but not sure how much of that power/complexity you need to accomplish the task.


#9

Not 100% on topic but it’s possible to scan or create a dep graph from the Cargo.toml and Cargo.lock and then scan if iron exists. This is what cargo-graph does (minus the iron scanning :wink: )


#10

If this is possible with the cargo APIs, might it be useful for cargo to make an easy interface for this via attributes? Similar to #[cfg(feature = "x")] except #[cfg(dependency = "y")]?