Pre-RFC: doc-dependencies

This Pre-RFC proposes to add a [doc-dependencies] property to Cargo.toml.

There are some proc-macro crates dedicated for generating documentation (not giving examples to avoid distraction on individual cases). It wastes compile time to compile these crates (which tend to use syn, which is an infamous compile time bottleneck) when they are not useful as transitive dependencies in cargo build etc., but they cannot be made dev-dependencies because they're still required for transitive dependencies in cargo doc.

[doc-dependencies] are compiled only when documentation needs to be generated. This includes transitive cargo doc and direct cargo test, the latter because of the generation of doc tests. Users of doc-dependencies should conditionally compile usages with gates such as cfg(rustdoc) and cfg(test).

1 Like

Currently I believe dependencies for documentation purposes are built as a normal metadata build, they do not activate cfg(rustdoc).

This proposal appears to imply changing that, and having a doc-specific metadata build for dependencies (based on [doc-dependencies] being transitive)?

I think that would make sense overall, and should probably be brought up on the doc_cfg feature even if this isn't added. If a crate is changing its documentation based on cfg(rustdoc) and you pub use a type from that crate you probably want its most intended documentation to appear in your crate as well.

This roughly agrees with my thoughts in Explicit "test" dependency grade? that the existing dependency grades we have are far too generic to be useful for various tasks, especially that they burden working on other targets with the need to compile the dependencies due to some unrelated target being forced to use the same dependency grade.

That we already have build-dependencies is a step in the right direction.

( deps required only for examples are a particular fly in my ointment )

What I'd also want to know is how this proposal intersects with rustdoc --test.

On one hand, it seems like documentation dependencies should be required for performing rustdoc tests.

On the other, its not 100% obvious if dependencies required for documentation-embedded tests should be required for building documentation.

True, seems not an easy problem. Recompiling all crates with cfg(rustdoc) when cargo doc is run sounds pretty bad. Is this the reason why cfg(rustdoc) is not yet stabilized?

I would say the overlap with Explicit "test" dependency grade? suggests that adding separate items in the Cargo metadata for each type is kind of ugly, and a features-bases approach (such as I proposed in that topic, too) would be a better option.

1 Like

I wonder if it would be possible to do some kind of pre-compilation pass on the source code (not just Cargo.toml) to determine which dependencies are actually used with the given configuration. This would benefit not just these use-cases (doc-only, test-only, example-only, etc) but also allow people building on Unix to not download and build Windows specific dependencies, et cetera.

It's theoretically possible if-and-only-if no macros from dependencies are used. Those macros can emit arbitrary paths that we would have no way of knowing without first compiling the dependency far enough to get the macro. A staged approach could theoretically work even through macros.

However, feature separation cannot be automatically derived. If only the #[cfg(test)] compilation needs the serde.derive feature, there's no generic way to detect that (as there's no tagging of exported APIs by required feature).

Also, explicit separation of dependencies helps document developer intent and lets the compiler help the developer.

2 Likes