Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass --cfg doc to check builds of dependencies as part of cargo doc/rustdoc #8811

Open
djrenren opened this issue Oct 26, 2020 · 6 comments
Open
Labels
C-bug Category: bug Command-doc Command-rustdoc S-needs-design Status: Needs someone to work further on the design for the feature or fix. NOT YET accepted.

Comments

@djrenren
Copy link

djrenren commented Oct 26, 2020

Problem
Some packages such as llvm-sys have workarounds that allow their docs to build on docs.rs despite the fact that no usable binary can be generated (in this case because it relies on a platform binary that is not present on docs.rs). Essentially it uses detection of #[cfg(doc)] to allow builds to succeed when they would otherwise fail. This works well today.

However, when this project is a dependency in another project, cargo doc will not just run rustdoc, it will also invoke rustc to perform a check build. This bypasses any #[cfg(doc)] protections because it runs without --cfg doc. It is currently not possible to detect that your crate is being compiled in check mode as part of a larger doc run. The desired build characteristics, however, are the same. We don't need a working binary, and we're invoking the compiler for the purpose of docs.

It's also very strange to have a case where cargo doc works on a project but not when that project is a dependency.

I've produced a minimal example of this that demonstrates the issue without all the cruft of thinking about LLVM and system dependencies.

Steps

  1. Clone djrenren/cargo-doc-failure
  2. cd app
  3. cargo rustdoc

Notice this fails while cargo rustdoc in the dependency succeeds.

Current Workarounds
Local workaround:
$ RUSTFLAGS="--cfg doc" cargo doc

Docs.rs workaround:
Cargo.toml:

[package.metadata.docs.rs]
rustc-args = [ "--cfg" , "doc"]

Suggested Solution(s)

  1. As suggested in the title of the issue, pass the doc config flag in while doing check builds as part of cargo rustdoc

  2. Provide a standard way to add cfg flags to libraries when built as part of rustdoc. That is, standardize what docs.rs already does so that it works locally as well.

Notes
This occurs on all cargo versions I've been able to find so the version is largely irrelevant, but let's say latest stable 1.47.0

Passing a doc flag by default to check builds could produce strange results if downstream crates use doc cfg's to change the interface of their crate, which may be a point in favor of solution 2.

@djrenren djrenren added the C-bug Category: bug label Oct 26, 2020
@djrenren
Copy link
Author

Also, I've marked this a bug, because of the unexpected behavior it produces, but I could see the argument to call it a feature request.

cdisselkoen added a commit to cdisselkoen/llvm-ir that referenced this issue Oct 27, 2020
cdisselkoen added a commit to cdisselkoen/llvm-ir that referenced this issue Oct 27, 2020
cdisselkoen added a commit to cdisselkoen/llvm-ir-analysis that referenced this issue Oct 27, 2020
@jyn514
Copy link
Member

jyn514 commented Oct 27, 2020

See also rust-lang/rust#76252.

@jyn514
Copy link
Member

jyn514 commented Oct 27, 2020

Note that crates have a tendency to do very cursed things when cfg(doc) is passed (https://doc.rust-lang.org/nightly/rustdoc/advanced-features.html#interactions-between-platform-specific-docs, rust-lang/rust#75100), so this will break crates in practice. I think the tradeoffs are worth it (since some crates will be broken either way), but any changes here should at least get a crater run.

See also the discussion in rust-lang/rust#77276 (comment).

jnqnfe added a commit to jnqnfe/pulse-binding-rust that referenced this issue Jul 29, 2021
it does not work to have these feature guards currently until rustc issue
#8811 ([1]) is fixed since we just get errors running `cargo test` or
`cargo doc` otherwise.

the problem stems from the fact that `--cfg doc` will be used for compiling
the main crate being processed but not its dependencies, thus here the
re-exports are enabled in the binding crate, but not the actual items in
the sys crate, and thus 'unresolved import' errors occur, complaining about
not being able to find the items in the sys crate.

note, it obviously would not hurt to just have these string constants
unguarded, but i felt that it would be perhaps nicer to use the guards and
associated feature documentation to highlight the version requirement for
the use of these two significant properties.

[1]: rust-lang/cargo#8811
@laplab
Copy link

laplab commented Apr 2, 2023

My team also suffers from similar problem. We are using different rustc version and nightly releases for generating documentation, mainly because they are more feature-rich at the moment. However, that makes some static assertions false, which we would rather avoid making in the first place when generating docs.

@ehuss Would the Cargo team be open to accepting contributions on this topic? Or do you feel like there is more discussion needed?

@weihanglo weihanglo added I-nominated-to-discuss To be discussed during issue triage on the next Cargo team meeting S-needs-team-input Status: Needs input from team on whether/how to proceed. labels Apr 26, 2023
@ehuss
Copy link
Contributor

ehuss commented May 2, 2023

The team discussed this a bit, and I think there is still quite a bit of open design exploration needed.

Some thoughts and questions:

  • Can this be distilled to just build.rs scripts? I see @laplab mentions they have static assertions that would have issues, but it's not clear what exactly those look like. What exactly are those static assertions? Can they be resolved in other ways?
  • There is potentially a very large performance and caching cost. The cargo doc cache is currently shared with cargo check. Splitting those could incur a very significant increase in build times for some users, and a large increase in disk usage for something that may not normally be needed.
  • There are other issues like Cargo doc does not pass --cfg doc for build scripts #8944 and Inform build scripts whether cargo is checking or building #4001 for figuring out how build scripts should behave for different scenarios like cargo check. I think I would echo the thoughts and questions in Inform build scripts whether cargo is checking or building #4001 (comment) about the viability and meaning of running build scripts in different modes.
  • We don't know the scope of the breakage this could have. It may be feasible for someone to do a crater run to get that data. If there is a large amount of breakage, then we would know for sure that a different approach would be needed.

@ehuss ehuss added S-needs-design Status: Needs someone to work further on the design for the feature or fix. NOT YET accepted. and removed I-nominated-to-discuss To be discussed during issue triage on the next Cargo team meeting S-needs-team-input Status: Needs input from team on whether/how to proceed. labels May 2, 2023
@djrenren
Copy link
Author

djrenren commented May 2, 2023

These are some fantastic thoughts. Thanks for taking the time to discuss. I hadn't thought of the caching problem and it is indeed super important to keep these caches working.

It gets me thinking that maybe this problem is better solved in the compiler. The llvm-sys example above delays error messages to post-build script, by setting an environment variable and putting the following code into the crate:

#[cfg(all(not(doc),LLVM_SYS_NOT_FOUND))]
std::compile_error!(/*...*/)

This approach runs into problems because there's no cfg flag for check builds, but if we imagine there was, then we could extend the llvm-sys approach to solve at least the problem that initiated this issue.

kezhuw added a commit to kezhuw/async-select that referenced this issue May 10, 2024
`#[cfg(doc)]` could change the interface and thus fail the build.

Refs:
 * rust-lang/cargo#8811
 * rust-lang/cargo#2025

changelog: changed
github-merge-queue bot pushed a commit to bevyengine/bevy that referenced this issue Aug 12, 2024
# Objective

- Fixes #14697

## Solution

This PR modifies the existing `all_tuples!` macro to optionally accept a
`#[doc(fake_variadic)]` attribute in its input. If the attribute is
present, each invocation of the impl macro gets the correct attributes
(i.e. the first impl receives `#[doc(fake_variadic)]` while the other
impls are hidden using `#[doc(hidden)]`.
Impls for the empty tuple (unit type) are left untouched (that's what
the [standard
library](https://doc.rust-lang.org/std/cmp/trait.PartialEq.html#impl-PartialEq-for-())
and
[serde](https://docs.rs/serde/latest/serde/trait.Serialize.html#impl-Serialize-for-())
do).

To work around rust-lang/cargo#8811 and to get
impls on re-exports to correctly show up as variadic, `--cfg docsrs_dep`
is passed when building the docs for the toplevel `bevy` crate.

`#[doc(fake_variadic)]` only works on tuples and fn pointers, so impls
for structs like `AnyOf<(T1, T2, ..., Tn)>` are unchanged.

## Testing

I built the docs locally using `RUSTDOCFLAGS='--cfg docsrs'
RUSTFLAGS='--cfg docsrs_dep' cargo +nightly doc --no-deps --workspace`
and checked the documentation page of a trait both in its original crate
and the re-exported version in `bevy`.
The description should correctly mention for how many tuple items the
trait is implemented.

I added `rustc-args` for docs.rs to the `bevy` crate, I hope there
aren't any other notable crates that re-export `#[doc(fake_variadic)]`
traits.

---

## Showcase

`bevy_ecs::query::QueryData`:
<img width="1015" alt="Screenshot 2024-08-12 at 16 41 28"
src="https://github.com/user-attachments/assets/d40136ed-6731-475f-91a0-9df255cd24e3">

`bevy::ecs::query::QueryData` (re-export):
<img width="1005" alt="Screenshot 2024-08-12 at 16 42 57"
src="https://github.com/user-attachments/assets/71d44cf0-0ab0-48b0-9a51-5ce332594e12">

## Original Description

<details>

Resolves #14697

Submitting as a draft for now, very WIP.

Unfortunately, the docs don't show the variadics nicely when looking at
reexported items.
For example:

`bevy_ecs::bundle::Bundle` correctly shows the variadic impl:

![image](https://github.com/user-attachments/assets/90bf8af1-1d1f-4714-9143-cdd3d0199998)

while `bevy::ecs::bundle::Bundle` (the reexport) shows all the impls
(not good):

![image](https://github.com/user-attachments/assets/439c428e-f712-465b-bec2-481f7bf5870b)

Built using `RUSTDOCFLAGS='--cfg docsrs' cargo +nightly doc --workspace
--no-deps` (`--no-deps` because of wgpu-core).

Maybe I missed something or this is a limitation in the *totally not
private* `#[doc(fake_variadic)]` thingy. In any case I desperately need
some sleep now :))

</details>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: bug Command-doc Command-rustdoc S-needs-design Status: Needs someone to work further on the design for the feature or fix. NOT YET accepted.
Projects
None yet
Development

No branches or pull requests

5 participants