Compile-time if dependency exists conditional?

Does exist crate of standard solution which allow get compile-time dependency conditional without introducing features?

Let's say: "if crate A has as dependency crate B" then compile the code.

Use case: procedural macro of crate X use declarative macro of crate Y. There is aggregating crate Z. I need macro working no matter which crate is used.

All optional dependencies automatically introduce features of the same name. What do you mean by "without introducing features"?

1 Like

You can't query for this, that's actually another way around: you can force your dependency to have its optional dependency included (and, yes, the Cargo features is the canonical way to do it). And you can't query the dependencies of the downstream or sibling crates at all - the dependencies graph is one-directional, you don't know anything about the user (aside from the things they told you).

4 Likes

Optional dependency introduce feature with the same name, right?
Does not non-optional dependency introduce feature with the same name?

Yes, every optional dependency introduces a corresponding feature.

No, non-optional dependencies do not introduce features.

4 Likes

Since it is non-optional, it's always present, so your check would be simplified anyway to the equivalent of if true.

4 Likes

Not really. What if the same file is used in two different crates simultaneously. One might have it, another don't have it. In my opinion Rust lacks means for introspection.

Reducing and rephrasing the problem:

  • several crates export procedural macro which use some declarative macro
  • for one crate the declarative macro is here ::crate1::declarative_macro, for another one it is here ::crate2::declarative_macro and ::crate1::declarative_macro is not available because crate1 is not immediate dependency.

But now I understand that I can duplicate dependency crate1 and make it immediate. That should solve the problem.

But that is not good solution because it forces to add to dependencies 10 crates instead of one :frowning:

If a crate A defines a macro that depends on a macro from another crate B, then A should re-export that macro (usually with #[doc(hidden)]) to avoid forcing clients to add a dependency to B.

1 Like

Thanks. Yes aggregator reexport declarative macro. But procedural macro expects to see it there ::crate1::declarative_macro, I see no means to tell it to look ::crate2::declarative_macro instead.