diff --git a/crates/project_model/src/build_scripts.rs b/crates/project_model/src/build_scripts.rs index 6b601c34a24a..d96c135ba5e3 100644 --- a/crates/project_model/src/build_scripts.rs +++ b/crates/project_model/src/build_scripts.rs @@ -42,22 +42,15 @@ pub(crate) struct BuildScriptOutput { } impl WorkspaceBuildScripts { - pub(crate) fn run( - config: &CargoConfig, - workspace: &CargoWorkspace, - progress: &dyn Fn(String), - ) -> Result { + fn build_command(config: &CargoConfig) -> Command { + if let Some([program, args @ ..]) = config.run_build_script_command.as_deref() { + let mut cmd = Command::new(program); + cmd.args(args); + return cmd; + } + let mut cmd = Command::new(toolchain::cargo()); - if config.wrap_rustc_in_build_scripts { - // Setup RUSTC_WRAPPER to point to `rust-analyzer` binary itself. We use - // that to compile only proc macros and build scripts during the initial - // `cargo check`. - let myself = std::env::current_exe()?; - cmd.env("RUSTC_WRAPPER", myself); - cmd.env("RA_RUSTC_WRAPPER", "1"); - } - cmd.current_dir(workspace.workspace_root()); cmd.args(&["check", "--quiet", "--workspace", "--message-format=json"]); // --all-targets includes tests, benches and examples in addition to the @@ -81,6 +74,26 @@ impl WorkspaceBuildScripts { } } + cmd + } + pub(crate) fn run( + config: &CargoConfig, + workspace: &CargoWorkspace, + progress: &dyn Fn(String), + ) -> Result { + let mut cmd = Self::build_command(config); + + if config.wrap_rustc_in_build_scripts { + // Setup RUSTC_WRAPPER to point to `rust-analyzer` binary itself. We use + // that to compile only proc macros and build scripts during the initial + // `cargo check`. + let myself = std::env::current_exe()?; + cmd.env("RUSTC_WRAPPER", myself); + cmd.env("RA_RUSTC_WRAPPER", "1"); + } + + cmd.current_dir(workspace.workspace_root()); + cmd.stdout(Stdio::piped()).stderr(Stdio::piped()).stdin(Stdio::null()); let mut res = WorkspaceBuildScripts::default(); @@ -104,7 +117,7 @@ impl WorkspaceBuildScripts { } // Copy-pasted from existing cargo_metadata. It seems like we - // should be using sered_stacker here? + // should be using serde_stacker here? let mut deserializer = serde_json::Deserializer::from_str(line); deserializer.disable_recursion_limit(); let message = Message::deserialize(&mut deserializer) diff --git a/crates/project_model/src/cargo_workspace.rs b/crates/project_model/src/cargo_workspace.rs index 48051e4b5e8f..76ef44e1471e 100644 --- a/crates/project_model/src/cargo_workspace.rs +++ b/crates/project_model/src/cargo_workspace.rs @@ -96,6 +96,8 @@ pub struct CargoConfig { pub unset_test_crates: UnsetTestCrates, pub wrap_rustc_in_build_scripts: bool, + + pub run_build_script_command: Option>, } impl CargoConfig { diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 958ff1fcee1f..c9d07a54bb43 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -79,6 +79,10 @@ config_data! { /// Run build scripts (`build.rs`) for more precise code analysis. cargo_runBuildScripts | cargo_loadOutDirsFromCheck: bool = "true", + /// Advanced option, fully override the command rust-analyzer uses to + /// run build scripts and build procedural macros. The command should + /// include `--message-format=json` or a similar option. + cargo_runBuildScriptsCommand: Option> = "null", /// Use `RUSTC_WRAPPER=rust-analyzer` when running build scripts to /// avoid compiling unnecessary things. cargo_useRustcWrapperForBuildScripts: bool = "true", @@ -803,6 +807,7 @@ impl Config { rustc_source, unset_test_crates: UnsetTestCrates::Only(self.data.cargo_unsetTest.clone()), wrap_rustc_in_build_scripts: self.data.cargo_useRustcWrapperForBuildScripts, + run_build_script_command: self.data.cargo_runBuildScriptsCommand.clone(), } } diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index d552982768b5..ace74f8e08af 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc @@ -64,6 +64,13 @@ List of features to activate. -- Run build scripts (`build.rs`) for more precise code analysis. -- +[[rust-analyzer.cargo.runBuildScriptsCommand]]rust-analyzer.cargo.runBuildScriptsCommand (default: `null`):: ++ +-- +Advanced option, fully override the command rust-analyzer uses to +run build scripts and build procedural macros. The command should +include `--message-format=json` or a similar option. +-- [[rust-analyzer.cargo.useRustcWrapperForBuildScripts]]rust-analyzer.cargo.useRustcWrapperForBuildScripts (default: `true`):: + -- diff --git a/editors/code/package.json b/editors/code/package.json index b7bc60a3b8b9..9dfae1a8a097 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -476,6 +476,17 @@ "default": true, "type": "boolean" }, + "rust-analyzer.cargo.runBuildScriptsCommand": { + "markdownDescription": "Advanced option, fully override the command rust-analyzer uses to\nrun build scripts and build procedural macros. The command should\ninclude `--message-format=json` or a similar option.", + "default": null, + "type": [ + "null", + "array" + ], + "items": { + "type": "string" + } + }, "rust-analyzer.cargo.useRustcWrapperForBuildScripts": { "markdownDescription": "Use `RUSTC_WRAPPER=rust-analyzer` when running build scripts to\navoid compiling unnecessary things.", "default": true,