72ae308c73
rust-analyzer's RUSTC_WRAPPER unconditionally succeeds `cargo check` invocations tripping up build scripts using `cargo check` to probe for successful compilations. To prevent this from happening the RUSTC_WRAPPER now checks if it's run from a build script by looking for the `CARGO_CFG_TARGET_ARCH` env var that cargo sets only when running build scripts.
52 lines
2.2 KiB
Rust
52 lines
2.2 KiB
Rust
//! We setup RUSTC_WRAPPER to point to `rust-analyzer` binary itself during the
|
|
//! initial `cargo check`. That way, we avoid checking the actual project, and
|
|
//! only build proc macros and build.rs.
|
|
//!
|
|
//! Code taken from IntelliJ :0)
|
|
//! https://github.com/intellij-rust/intellij-rust/blob/master/native-helper/src/main.rs
|
|
use std::{
|
|
ffi::OsString,
|
|
io,
|
|
process::{Command, Stdio},
|
|
};
|
|
|
|
/// ExitCode/ExitStatus are impossible to create :(.
|
|
pub(crate) struct ExitCode(pub(crate) Option<i32>);
|
|
|
|
pub(crate) fn run_rustc_skipping_cargo_checking(
|
|
rustc_executable: OsString,
|
|
args: Vec<OsString>,
|
|
) -> io::Result<ExitCode> {
|
|
// `CARGO_CFG_TARGET_ARCH` is only set by cargo when executing build scripts
|
|
// We don't want to exit out checks unconditionally with success if a build
|
|
// script tries to invoke checks themselves
|
|
// See https://github.com/rust-lang/rust-analyzer/issues/12973 for context
|
|
let not_invoked_by_build_script = std::env::var_os("CARGO_CFG_TARGET_ARCH").is_none();
|
|
let is_cargo_check = args.iter().any(|arg| {
|
|
let arg = arg.to_string_lossy();
|
|
// `cargo check` invokes `rustc` with `--emit=metadata` argument.
|
|
//
|
|
// https://doc.rust-lang.org/rustc/command-line-arguments.html#--emit-specifies-the-types-of-output-files-to-generate
|
|
// link — Generates the crates specified by --crate-type. The default
|
|
// output filenames depend on the crate type and platform. This
|
|
// is the default if --emit is not specified.
|
|
// metadata — Generates a file containing metadata about the crate.
|
|
// The default output filename is CRATE_NAME.rmeta.
|
|
arg.starts_with("--emit=") && arg.contains("metadata") && !arg.contains("link")
|
|
});
|
|
if not_invoked_by_build_script && is_cargo_check {
|
|
return Ok(ExitCode(Some(0)));
|
|
}
|
|
run_rustc(rustc_executable, args)
|
|
}
|
|
|
|
fn run_rustc(rustc_executable: OsString, args: Vec<OsString>) -> io::Result<ExitCode> {
|
|
let mut child = Command::new(rustc_executable)
|
|
.args(args)
|
|
.stdin(Stdio::inherit())
|
|
.stdout(Stdio::inherit())
|
|
.stderr(Stdio::inherit())
|
|
.spawn()?;
|
|
Ok(ExitCode(child.wait()?.code()))
|
|
}
|