cuviper / autocfg

Automatic cfg for Rust compiler features
Apache License 2.0
95 stars 24 forks source link

autocfg still calls rustc without the wrapper #58

Closed RalfJung closed 4 months ago

RalfJung commented 5 months ago

I'm playing around with a patched version of cargo that lets me set

RUSTC_WRAPPER=<my binary here>
RUSTC=/path/that/does/not/exist

This makes it immediately obvious when something bypasses RUSTC_WRAPPER.

And it turns out this makes autocfg panic. I think it's this call that is not wrapped:

https://github.com/cuviper/autocfg/blob/c10bc170ca6cc8176b046dce8d7e73e8b24f6d76/src/lib.rs#L160

cuviper commented 5 months ago

Hmm... I'm not sure that we should, given rust-lang/cargo#10885, but I suppose if cargo is willing to change then we can follow suit. We can't make that behavior conditional on version, since that's what we're probing there, but maybe if the wrapper fails we can try again without it.

dtolnay commented 5 months ago

This might alternatively be a feature request for Cargo. Do RUSTC_WRAPPER and RUSTC_WORKSPACE_WRAPPER even need to be exposed to build scripts, or should Cargo unset those when running the build script and instead provide a RUSTC (or PATH containing a rustc?) which is a shim executable that already has baked in the right wrappers?

Exposing the original *_WRAPPER variables to build scripts is only useful if we want build scripts to be able to run those rustc wrappers with the build script's own choice of rustc different from the current one, which seems dubious. The downside of exposing the original variables to build scripts is... we're counting on every build script to incorporate relatively verbose code to apply both these wrappers correctly, as in this issue.

Possible implementations for fixing this on the Cargo side include:

Any of these, especially the last one, seems better than boiling the ocean to update every real-world build script.

RalfJung commented 5 months ago

This might alternatively be a feature request for Cargo.

Sounds like a new approach to resolve this feature request: https://github.com/rust-lang/cargo/issues/11244

cuviper commented 5 months ago

better than boiling the ocean to update every real-world build script.

I would expect it's more of a pond than an ocean -- do you really think manual rustc probing is so common?

dtolnay commented 5 months ago

This kind of thing is common: https://github.com/dtolnay/semver/blob/1.0.22/build.rs#L67-L68

In my own crates, the build scripts are written so that if $RUSTC --version fails then the fallback configuration corresponds to a default relatively recent stable rustc. But in the rest of the ecosystem, my impression is it's much more common that build scripts default to assuming a super old rustc, or fail altogether, so this interacts poorly with Ralf's RUSTC=/path/that/does/not/exist patch.

Some examples in high-profile crates:

And here's hundreds more uses of $RUSTC: https://github.com/search?q=%2F%5Cbvar(_os)%3F%5C(%22RUSTC%22%5C)%2F%20path%3Abuild.rs&type=code. Who knows what they're all doing but practically none of them pay attention to *_WRAPPER.

cuviper commented 5 months ago

Ouch, that's a lot more than I expected...

RalfJung commented 5 months ago

Yeah... that makes setting RUSTC to a non-existent path not very appealing. :/

So maybe the farthest we can go is to say that if you invoke RUSTC directly without the wrapper all you should do is query the version. You definitely can't expect the sysroot to be the same as with the wrapper though, and you can't expect direct RUSTC invocations to support the target indicated by TARGET.

RalfJung commented 5 months ago

That said, rustc bootstrap may still want to require the wrapper to be called even for --version. We can be picky about dependencies there, and making such a requirement could simplify some of the logic and make it less likely that bootstrap's sysroot management is accidentally circumvented.

taiki-e commented 4 months ago

FYI, clippy-deriver is one of the wrappers that currently does not work properly in the use case of getting the rustc version.

$ clippy-driver rustc --version                                              
clippy 0.1.79 (f9b16149 2024-04-19)

$ clippy-driver rustc --version --verbose
clippy 0.1.79 (f9b16149 2024-04-19)

$ clippy-driver rustc --rustc --version  
rustc 1.79.0-nightly (f9b161492 2024-04-19)

$ clippy-driver rustc --rustc --version --verbose
rustc 1.79.0-nightly (f9b161492 2024-04-19)
binary: rustc
commit-hash: f9b16149208c8a8a349c32813312716f6603eb6f
commit-date: 2024-04-19
host: aarch64-apple-darwin
release: 1.79.0-nightly
LLVM version: 18.1.4

$ clippy-driver rustc -V
clippy 0.1.79 (f9b16149 2024-04-19)

$ clippy-driver rustc -Vv
rustc 1.79.0-nightly (f9b161492 2024-04-19)
binary: rustc
commit-hash: f9b16149208c8a8a349c32813312716f6603eb6f
commit-date: 2024-04-19
host: aarch64-apple-darwin
release: 1.79.0-nightly
LLVM version: 18.1.4

$ clippy-driver rustc -vV
rustc 1.79.0-nightly (f9b161492 2024-04-19)
binary: rustc
commit-hash: f9b16149208c8a8a349c32813312716f6603eb6f
commit-date: 2024-04-19
host: aarch64-apple-darwin
release: 1.79.0-nightly
LLVM version: 18.1.4

AFAIK clippy-driver is usually only used as RUSTC_WORKSPACE_WRAPPER, so I think we could work around the problem by applying only RUSTC_WRAPPER when getting the rustc version. (The bug should be fixed on the clippy side, but a workaround is needed anyway, since rustc version detection needs to work with older toolchains.)

Since RUSTC_WORKSPACE_WRAPPER applies only for workspace members, unlike RUSTC_WRAPPER which applies for all crates, it should not change the toolchain (since it will result in linking crates compiled with different rustc versions). So ignoring RUSTC_WORKSPACE_WRAPPER when getting the rustc version should not affect the correctness of the results.

RalfJung commented 4 months ago

Why is clippy-driver even a wrapper? The equivalent miri binary is not.

I would argue this is a bug in clippy-driver. A wrapper is supposed to wrap the rustc invocation, not change its --version output. The fact that -Vv and --version --verbose behave differently also shows that clippy-driver is behaving sketchy here.

RalfJung commented 4 months ago

Filed as a clippy bug: https://github.com/rust-lang/rust-clippy/issues/12697

cuviper commented 4 months ago

It also seems weird to me that the clippy wrapper would be set while executing a build script, but so it is...

RalfJung commented 4 months ago

That is expected, it is set for the entire "cargo clippy" invocation and cargo does not unset anything for build scripts. After all build scripts should also honor which RUSTC cargo invokes (and with which wrapper).