Unnamed repository; edit this file 'description' to name the repository.
Add cargo.extraEnv setting
Daniel Paoliello 2022-09-14
parent f64c956 · commit c407cc5
-rw-r--r--Cargo.lock1
-rw-r--r--crates/flycheck/Cargo.toml1
-rw-r--r--crates/flycheck/src/lib.rs10
-rw-r--r--crates/project-model/src/build_scripts.rs2
-rw-r--r--crates/project-model/src/cargo_workspace.rs36
-rw-r--r--crates/project-model/src/rustc_cfg.rs18
-rw-r--r--crates/project-model/src/sysroot.rs19
-rw-r--r--crates/project-model/src/tests.rs22
-rw-r--r--crates/project-model/src/workspace.rs24
-rw-r--r--crates/rust-analyzer/src/cli/analysis_stats.rs3
-rw-r--r--crates/rust-analyzer/src/cli/load_cargo.rs4
-rw-r--r--crates/rust-analyzer/src/cli/lsif.rs3
-rw-r--r--crates/rust-analyzer/src/cli/scip.rs2
-rw-r--r--crates/rust-analyzer/src/config.rs23
-rw-r--r--crates/rust-analyzer/src/handlers.rs2
-rw-r--r--crates/rust-analyzer/src/reload.rs7
-rw-r--r--docs/user/generated_config.adoc11
-rw-r--r--editors/code/package.json10
18 files changed, 155 insertions, 43 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 9f10d92c4e..8c6d25f7e8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -394,6 +394,7 @@ dependencies = [
"crossbeam-channel",
"jod-thread",
"paths",
+ "rustc-hash",
"serde",
"serde_json",
"stdx",
diff --git a/crates/flycheck/Cargo.toml b/crates/flycheck/Cargo.toml
index d3d180ece5..688e790c53 100644
--- a/crates/flycheck/Cargo.toml
+++ b/crates/flycheck/Cargo.toml
@@ -13,6 +13,7 @@ doctest = false
crossbeam-channel = "0.5.5"
tracing = "0.1.35"
cargo_metadata = "0.15.0"
+rustc-hash = "1.1.0"
serde = { version = "1.0.137", features = ["derive"] }
serde_json = "1.0.81"
jod-thread = "0.1.2"
diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs
index d9f4ef5b7f..fdc03f4053 100644
--- a/crates/flycheck/src/lib.rs
+++ b/crates/flycheck/src/lib.rs
@@ -12,6 +12,7 @@ use std::{
use crossbeam_channel::{never, select, unbounded, Receiver, Sender};
use paths::AbsPathBuf;
+use rustc_hash::FxHashMap;
use serde::Deserialize;
use stdx::{process::streaming_output, JodChild};
@@ -30,10 +31,12 @@ pub enum FlycheckConfig {
all_features: bool,
features: Vec<String>,
extra_args: Vec<String>,
+ extra_env: FxHashMap<String, String>,
},
CustomCommand {
command: String,
args: Vec<String>,
+ extra_env: FxHashMap<String, String>,
},
}
@@ -41,7 +44,7 @@ impl fmt::Display for FlycheckConfig {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
FlycheckConfig::CargoCommand { command, .. } => write!(f, "cargo {}", command),
- FlycheckConfig::CustomCommand { command, args } => {
+ FlycheckConfig::CustomCommand { command, args, .. } => {
write!(f, "{} {}", command, args.join(" "))
}
}
@@ -256,6 +259,7 @@ impl FlycheckActor {
all_features,
extra_args,
features,
+ extra_env,
} => {
let mut cmd = Command::new(toolchain::cargo());
cmd.arg(command);
@@ -281,11 +285,13 @@ impl FlycheckActor {
}
}
cmd.args(extra_args);
+ cmd.envs(extra_env);
cmd
}
- FlycheckConfig::CustomCommand { command, args } => {
+ FlycheckConfig::CustomCommand { command, args, extra_env } => {
let mut cmd = Command::new(command);
cmd.args(args);
+ cmd.envs(extra_env);
cmd
}
};
diff --git a/crates/project-model/src/build_scripts.rs b/crates/project-model/src/build_scripts.rs
index 84e772d168..837ea01619 100644
--- a/crates/project-model/src/build_scripts.rs
+++ b/crates/project-model/src/build_scripts.rs
@@ -43,10 +43,12 @@ impl WorkspaceBuildScripts {
if let Some([program, args @ ..]) = config.run_build_script_command.as_deref() {
let mut cmd = Command::new(program);
cmd.args(args);
+ cmd.envs(&config.extra_env);
return cmd;
}
let mut cmd = Command::new(toolchain::cargo());
+ cmd.envs(&config.extra_env);
cmd.args(&["check", "--quiet", "--workspace", "--message-format=json"]);
diff --git a/crates/project-model/src/cargo_workspace.rs b/crates/project-model/src/cargo_workspace.rs
index eed955b42d..736d80041b 100644
--- a/crates/project-model/src/cargo_workspace.rs
+++ b/crates/project-model/src/cargo_workspace.rs
@@ -2,6 +2,7 @@
use std::iter;
use std::path::PathBuf;
+use std::str::from_utf8;
use std::{ops, process::Command};
use anyhow::{Context, Result};
@@ -98,6 +99,8 @@ pub struct CargoConfig {
pub wrap_rustc_in_build_scripts: bool,
pub run_build_script_command: Option<Vec<String>>,
+
+ pub extra_env: FxHashMap<String, String>,
}
impl CargoConfig {
@@ -263,8 +266,8 @@ impl CargoWorkspace {
let target = config
.target
.clone()
- .or_else(|| cargo_config_build_target(cargo_toml))
- .or_else(|| rustc_discover_host_triple(cargo_toml));
+ .or_else(|| cargo_config_build_target(cargo_toml, config))
+ .or_else(|| rustc_discover_host_triple(cargo_toml, config));
let mut meta = MetadataCommand::new();
meta.cargo_path(toolchain::cargo());
@@ -292,8 +295,27 @@ impl CargoWorkspace {
// unclear whether cargo itself supports it.
progress("metadata".to_string());
- let meta =
- meta.exec().with_context(|| format!("Failed to run `{:?}`", meta.cargo_command()))?;
+ fn exec_with_env(
+ command: &cargo_metadata::MetadataCommand,
+ extra_env: &FxHashMap<String, String>,
+ ) -> Result<cargo_metadata::Metadata, cargo_metadata::Error> {
+ let mut command = command.cargo_command();
+ command.envs(extra_env);
+ let output = command.output()?;
+ if !output.status.success() {
+ return Err(cargo_metadata::Error::CargoMetadata {
+ stderr: String::from_utf8(output.stderr)?,
+ });
+ }
+ let stdout = from_utf8(&output.stdout)?
+ .lines()
+ .find(|line| line.starts_with('{'))
+ .ok_or(cargo_metadata::Error::NoJson)?;
+ cargo_metadata::MetadataCommand::parse(stdout)
+ }
+
+ let meta = exec_with_env(&meta, &config.extra_env)
+ .with_context(|| format!("Failed to run `{:?}`", meta.cargo_command()))?;
Ok(meta)
}
@@ -463,8 +485,9 @@ impl CargoWorkspace {
}
}
-fn rustc_discover_host_triple(cargo_toml: &ManifestPath) -> Option<String> {
+fn rustc_discover_host_triple(cargo_toml: &ManifestPath, config: &CargoConfig) -> Option<String> {
let mut rustc = Command::new(toolchain::rustc());
+ rustc.envs(&config.extra_env);
rustc.current_dir(cargo_toml.parent()).arg("-vV");
tracing::debug!("Discovering host platform by {:?}", rustc);
match utf8_stdout(rustc) {
@@ -486,8 +509,9 @@ fn rustc_discover_host_triple(cargo_toml: &ManifestPath) -> Option<String> {
}
}
-fn cargo_config_build_target(cargo_toml: &ManifestPath) -> Option<String> {
+fn cargo_config_build_target(cargo_toml: &ManifestPath, config: &CargoConfig) -> Option<String> {
let mut cargo_config = Command::new(toolchain::cargo());
+ cargo_config.envs(&config.extra_env);
cargo_config
.current_dir(cargo_toml.parent())
.args(&["-Z", "unstable-options", "config", "get", "build.target"])
diff --git a/crates/project-model/src/rustc_cfg.rs b/crates/project-model/src/rustc_cfg.rs
index 17e244d064..486cb143b8 100644
--- a/crates/project-model/src/rustc_cfg.rs
+++ b/crates/project-model/src/rustc_cfg.rs
@@ -4,9 +4,13 @@ use std::process::Command;
use anyhow::Result;
-use crate::{cfg_flag::CfgFlag, utf8_stdout, ManifestPath};
+use crate::{cfg_flag::CfgFlag, utf8_stdout, CargoConfig, ManifestPath};
-pub(crate) fn get(cargo_toml: Option<&ManifestPath>, target: Option<&str>) -> Vec<CfgFlag> {
+pub(crate) fn get(
+ cargo_toml: Option<&ManifestPath>,
+ target: Option<&str>,
+ config: &CargoConfig,
+) -> Vec<CfgFlag> {
let _p = profile::span("rustc_cfg::get");
let mut res = Vec::with_capacity(6 * 2 + 1);
@@ -18,7 +22,7 @@ pub(crate) fn get(cargo_toml: Option<&ManifestPath>, target: Option<&str>) -> Ve
}
}
- match get_rust_cfgs(cargo_toml, target) {
+ match get_rust_cfgs(cargo_toml, target, config) {
Ok(rustc_cfgs) => {
tracing::debug!(
"rustc cfgs found: {:?}",
@@ -35,9 +39,14 @@ pub(crate) fn get(cargo_toml: Option<&ManifestPath>, target: Option<&str>) -> Ve
res
}
-fn get_rust_cfgs(cargo_toml: Option<&ManifestPath>, target: Option<&str>) -> Result<String> {
+fn get_rust_cfgs(
+ cargo_toml: Option<&ManifestPath>,
+ target: Option<&str>,
+ config: &CargoConfig,
+) -> Result<String> {
if let Some(cargo_toml) = cargo_toml {
let mut cargo_config = Command::new(toolchain::cargo());
+ cargo_config.envs(&config.extra_env);
cargo_config
.current_dir(cargo_toml.parent())
.args(&["-Z", "unstable-options", "rustc", "--print", "cfg"])
@@ -52,6 +61,7 @@ fn get_rust_cfgs(cargo_toml: Option<&ManifestPath>, target: Option<&str>) -> Res
}
// using unstable cargo features failed, fall back to using plain rustc
let mut cmd = Command::new(toolchain::rustc());
+ cmd.envs(&config.extra_env);
cmd.args(&["--print", "cfg", "-O"]);
if let Some(target) = target {
cmd.args(&["--target", target]);
diff --git a/crates/project-model/src/sysroot.rs b/crates/project-model/src/sysroot.rs
index 362bb0f5e7..3282719fef 100644
--- a/crates/project-model/src/sysroot.rs
+++ b/crates/project-model/src/sysroot.rs
@@ -10,7 +10,7 @@ use anyhow::{format_err, Result};
use la_arena::{Arena, Idx};
use paths::{AbsPath, AbsPathBuf};
-use crate::{utf8_stdout, ManifestPath};
+use crate::{utf8_stdout, CargoConfig, ManifestPath};
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Sysroot {
@@ -67,18 +67,20 @@ impl Sysroot {
self.crates.iter().map(|(id, _data)| id)
}
- pub fn discover(dir: &AbsPath) -> Result<Sysroot> {
+ pub fn discover(dir: &AbsPath, config: &CargoConfig) -> Result<Sysroot> {
tracing::debug!("Discovering sysroot for {}", dir.display());
- let sysroot_dir = discover_sysroot_dir(dir)?;
- let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir, dir)?;
+ let sysroot_dir = discover_sysroot_dir(dir, config)?;
+ let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir, dir, config)?;
let res = Sysroot::load(sysroot_dir, sysroot_src_dir)?;
Ok(res)
}
- pub fn discover_rustc(cargo_toml: &ManifestPath) -> Option<ManifestPath> {
+ pub fn discover_rustc(cargo_toml: &ManifestPath, config: &CargoConfig) -> Option<ManifestPath> {
tracing::debug!("Discovering rustc source for {}", cargo_toml.display());
let current_dir = cargo_toml.parent();
- discover_sysroot_dir(current_dir).ok().and_then(|sysroot_dir| get_rustc_src(&sysroot_dir))
+ discover_sysroot_dir(current_dir, config)
+ .ok()
+ .and_then(|sysroot_dir| get_rustc_src(&sysroot_dir))
}
pub fn load(sysroot_dir: AbsPathBuf, sysroot_src_dir: AbsPathBuf) -> Result<Sysroot> {
@@ -144,8 +146,9 @@ impl Sysroot {
}
}
-fn discover_sysroot_dir(current_dir: &AbsPath) -> Result<AbsPathBuf> {
+fn discover_sysroot_dir(current_dir: &AbsPath, config: &CargoConfig) -> Result<AbsPathBuf> {
let mut rustc = Command::new(toolchain::rustc());
+ rustc.envs(&config.extra_env);
rustc.current_dir(current_dir).args(&["--print", "sysroot"]);
tracing::debug!("Discovering sysroot by {:?}", rustc);
let stdout = utf8_stdout(rustc)?;
@@ -155,6 +158,7 @@ fn discover_sysroot_dir(current_dir: &AbsPath) -> Result<AbsPathBuf> {
fn discover_sysroot_src_dir(
sysroot_path: &AbsPathBuf,
current_dir: &AbsPath,
+ config: &CargoConfig,
) -> Result<AbsPathBuf> {
if let Ok(path) = env::var("RUST_SRC_PATH") {
let path = AbsPathBuf::try_from(path.as_str())
@@ -170,6 +174,7 @@ fn discover_sysroot_src_dir(
get_rust_src(sysroot_path)
.or_else(|| {
let mut rustup = Command::new(toolchain::rustup());
+ rustup.envs(&config.extra_env);
rustup.current_dir(current_dir).args(&["component", "add", "rust-src"]);
utf8_stdout(rustup).ok()?;
get_rust_src(sysroot_path)
diff --git a/crates/project-model/src/tests.rs b/crates/project-model/src/tests.rs
index 9ccb6e9101..bea624bd54 100644
--- a/crates/project-model/src/tests.rs
+++ b/crates/project-model/src/tests.rs
@@ -10,8 +10,8 @@ use paths::{AbsPath, AbsPathBuf};
use serde::de::DeserializeOwned;
use crate::{
- CargoWorkspace, CfgOverrides, ProjectJson, ProjectJsonData, ProjectWorkspace, Sysroot,
- WorkspaceBuildScripts,
+ CargoConfig, CargoWorkspace, CfgOverrides, ProjectJson, ProjectJsonData, ProjectWorkspace,
+ Sysroot, WorkspaceBuildScripts,
};
fn load_cargo(file: &str) -> CrateGraph {
@@ -92,13 +92,17 @@ fn rooted_project_json(data: ProjectJsonData) -> ProjectJson {
}
fn to_crate_graph(project_workspace: ProjectWorkspace) -> CrateGraph {
- project_workspace.to_crate_graph(&mut |_, _| Ok(Vec::new()), &mut {
- let mut counter = 0;
- move |_path| {
- counter += 1;
- Some(FileId(counter))
- }
- })
+ project_workspace.to_crate_graph(
+ &mut |_, _| Ok(Vec::new()),
+ &mut {
+ let mut counter = 0;
+ move |_path| {
+ counter += 1;
+ Some(FileId(counter))
+ }
+ },
+ &CargoConfig::default(),
+ )
}
fn check_crate_graph(crate_graph: CrateGraph, expect: Expect) {
diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs
index 818bbed6af..bc4ab45dae 100644
--- a/crates/project-model/src/workspace.rs
+++ b/crates/project-model/src/workspace.rs
@@ -156,11 +156,12 @@ impl ProjectWorkspace {
})?;
let project_location = project_json.parent().to_path_buf();
let project_json = ProjectJson::new(&project_location, data);
- ProjectWorkspace::load_inline(project_json, config.target.as_deref())?
+ ProjectWorkspace::load_inline(project_json, config.target.as_deref(), config)?
}
ProjectManifest::CargoToml(cargo_toml) => {
let cargo_version = utf8_stdout({
let mut cmd = Command::new(toolchain::cargo());
+ cmd.envs(&config.extra_env);
cmd.arg("--version");
cmd
})?;
@@ -186,7 +187,7 @@ impl ProjectWorkspace {
let sysroot = if config.no_sysroot {
None
} else {
- Some(Sysroot::discover(cargo_toml.parent()).with_context(|| {
+ Some(Sysroot::discover(cargo_toml.parent(), config).with_context(|| {
format!(
"Failed to find sysroot for Cargo.toml file {}. Is rust-src installed?",
cargo_toml.display()
@@ -196,7 +197,7 @@ impl ProjectWorkspace {
let rustc_dir = match &config.rustc_source {
Some(RustcSource::Path(path)) => ManifestPath::try_from(path.clone()).ok(),
- Some(RustcSource::Discover) => Sysroot::discover_rustc(&cargo_toml),
+ Some(RustcSource::Discover) => Sysroot::discover_rustc(&cargo_toml, config),
None => None,
};
@@ -216,7 +217,7 @@ impl ProjectWorkspace {
None => None,
};
- let rustc_cfg = rustc_cfg::get(Some(&cargo_toml), config.target.as_deref());
+ let rustc_cfg = rustc_cfg::get(Some(&cargo_toml), config.target.as_deref(), config);
let cfg_overrides = config.cfg_overrides();
ProjectWorkspace::Cargo {
@@ -237,6 +238,7 @@ impl ProjectWorkspace {
pub fn load_inline(
project_json: ProjectJson,
target: Option<&str>,
+ config: &CargoConfig,
) -> Result<ProjectWorkspace> {
let sysroot = match (project_json.sysroot.clone(), project_json.sysroot_src.clone()) {
(Some(sysroot), Some(sysroot_src)) => Some(Sysroot::load(sysroot, sysroot_src)?),
@@ -258,7 +260,7 @@ impl ProjectWorkspace {
(None, None) => None,
};
- let rustc_cfg = rustc_cfg::get(None, target);
+ let rustc_cfg = rustc_cfg::get(None, target, config);
Ok(ProjectWorkspace::Json { project: project_json, sysroot, rustc_cfg })
}
@@ -268,8 +270,9 @@ impl ProjectWorkspace {
.first()
.and_then(|it| it.parent())
.ok_or_else(|| format_err!("No detached files to load"))?,
+ &CargoConfig::default(),
)?;
- let rustc_cfg = rustc_cfg::get(None, None);
+ let rustc_cfg = rustc_cfg::get(None, None, &CargoConfig::default());
Ok(ProjectWorkspace::DetachedFiles { files: detached_files, sysroot, rustc_cfg })
}
@@ -416,6 +419,7 @@ impl ProjectWorkspace {
&self,
load_proc_macro: &mut dyn FnMut(&str, &AbsPath) -> ProcMacroLoadResult,
load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
+ config: &CargoConfig,
) -> CrateGraph {
let _p = profile::span("ProjectWorkspace::to_crate_graph");
@@ -426,6 +430,7 @@ impl ProjectWorkspace {
load,
project,
sysroot,
+ config,
),
ProjectWorkspace::Cargo {
cargo,
@@ -464,6 +469,7 @@ fn project_json_to_crate_graph(
load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
project: &ProjectJson,
sysroot: &Option<Sysroot>,
+ config: &CargoConfig,
) -> CrateGraph {
let mut crate_graph = CrateGraph::default();
let sysroot_deps = sysroot
@@ -489,9 +495,9 @@ fn project_json_to_crate_graph(
};
let target_cfgs = match krate.target.as_deref() {
- Some(target) => {
- cfg_cache.entry(target).or_insert_with(|| rustc_cfg::get(None, Some(target)))
- }
+ Some(target) => cfg_cache
+ .entry(target)
+ .or_insert_with(|| rustc_cfg::get(None, Some(target), config)),
None => &rustc_cfg,
};
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs
index f52e1e7512..80128e43fd 100644
--- a/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -80,7 +80,8 @@ impl flags::AnalysisStats {
Some(build_scripts_sw.elapsed())
};
- let (host, vfs, _proc_macro) = load_workspace(workspace, &load_cargo_config)?;
+ let (host, vfs, _proc_macro) =
+ load_workspace(workspace, &cargo_config, &load_cargo_config)?;
let db = host.raw_database();
eprint!("{:<20} {}", "Database loaded:", db_load_sw.elapsed());
eprint!(" (metadata {}", metadata_time);
diff --git a/crates/rust-analyzer/src/cli/load_cargo.rs b/crates/rust-analyzer/src/cli/load_cargo.rs
index 5d1c013c32..88953096e2 100644
--- a/crates/rust-analyzer/src/cli/load_cargo.rs
+++ b/crates/rust-analyzer/src/cli/load_cargo.rs
@@ -38,7 +38,7 @@ pub fn load_workspace_at(
workspace.set_build_scripts(build_scripts)
}
- load_workspace(workspace, load_config)
+ load_workspace(workspace, cargo_config, load_config)
}
// Note: Since this function is used by external tools that use rust-analyzer as a library
@@ -48,6 +48,7 @@ pub fn load_workspace_at(
// these tools need access to `ProjectWorkspace`, too, which `load_workspace_at` hides.
pub fn load_workspace(
ws: ProjectWorkspace,
+ cargo_config: &CargoConfig,
load_config: &LoadCargoConfig,
) -> Result<(AnalysisHost, vfs::Vfs, Option<ProcMacroServer>)> {
let (sender, receiver) = unbounded();
@@ -75,6 +76,7 @@ pub fn load_workspace(
vfs.set_file_contents(path.clone(), contents);
vfs.file_id(&path)
},
+ cargo_config,
);
let project_folders = ProjectFolders::new(&[ws], &[]);
diff --git a/crates/rust-analyzer/src/cli/lsif.rs b/crates/rust-analyzer/src/cli/lsif.rs
index 491c55a04f..79577bf78c 100644
--- a/crates/rust-analyzer/src/cli/lsif.rs
+++ b/crates/rust-analyzer/src/cli/lsif.rs
@@ -299,7 +299,8 @@ impl flags::Lsif {
let workspace = ProjectWorkspace::load(manifest, &cargo_config, no_progress)?;
- let (host, vfs, _proc_macro) = load_workspace(workspace, &load_cargo_config)?;
+ let (host, vfs, _proc_macro) =
+ load_workspace(workspace, &cargo_config, &load_cargo_config)?;
let db = host.raw_database();
let analysis = host.analysis();
diff --git a/crates/rust-analyzer/src/cli/scip.rs b/crates/rust-analyzer/src/cli/scip.rs
index 65cc993c45..05c16bb39e 100644
--- a/crates/rust-analyzer/src/cli/scip.rs
+++ b/crates/rust-analyzer/src/cli/scip.rs
@@ -40,7 +40,7 @@ impl flags::Scip {
let workspace = ProjectWorkspace::load(manifest, &cargo_config, no_progress)?;
- let (host, vfs, _) = load_workspace(workspace, &load_cargo_config)?;
+ let (host, vfs, _) = load_workspace(workspace, &cargo_config, &load_cargo_config)?;
let db = host.raw_database();
let analysis = host.analysis();
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index e0384e67d4..2cf7a3c85b 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -84,6 +84,9 @@ config_data! {
/// Use `RUSTC_WRAPPER=rust-analyzer` when running build scripts to
/// avoid checking unnecessary things.
cargo_buildScripts_useRustcWrapper: bool = "true",
+ /// Extra environment variables that will be set when running cargo, rustc
+ /// or other commands within the workspace. Useful for setting RUSTFLAGS.
+ cargo_extraEnv: FxHashMap<String, String> = "{}",
/// List of features to activate.
///
/// Set this to `"all"` to pass `--all-features` to cargo.
@@ -105,6 +108,8 @@ config_data! {
checkOnSave_enable: bool = "true",
/// Extra arguments for `cargo check`.
checkOnSave_extraArgs: Vec<String> = "[]",
+ /// Extra environment variables that will be set when running `cargo check`.
+ checkOnSave_extraEnv: FxHashMap<String, String> = "{}",
/// List of features to activate. Defaults to
/// `#rust-analyzer.cargo.features#`.
///
@@ -934,6 +939,16 @@ impl Config {
}
}
+ pub fn extra_env(&self) -> &FxHashMap<String, String> {
+ &self.data.cargo_extraEnv
+ }
+
+ pub fn check_on_save_extra_env(&self) -> FxHashMap<String, String> {
+ let mut extra_env = self.data.cargo_extraEnv.clone();
+ extra_env.extend(self.data.checkOnSave_extraEnv.clone());
+ extra_env
+ }
+
pub fn lru_capacity(&self) -> Option<usize> {
self.data.lru_capacity
}
@@ -1003,6 +1018,7 @@ impl Config {
unset_test_crates: UnsetTestCrates::Only(self.data.cargo_unsetTest.clone()),
wrap_rustc_in_build_scripts: self.data.cargo_buildScripts_useRustcWrapper,
run_build_script_command: self.data.cargo_buildScripts_overrideCommand.clone(),
+ extra_env: self.data.cargo_extraEnv.clone(),
}
}
@@ -1028,7 +1044,11 @@ impl Config {
Some(args) if !args.is_empty() => {
let mut args = args.clone();
let command = args.remove(0);
- FlycheckConfig::CustomCommand { command, args }
+ FlycheckConfig::CustomCommand {
+ command,
+ args,
+ extra_env: self.check_on_save_extra_env(),
+ }
}
Some(_) | None => FlycheckConfig::CargoCommand {
command: self.data.checkOnSave_command.clone(),
@@ -1056,6 +1076,7 @@ impl Config {
CargoFeatures::Listed(it) => it,
},
extra_args: self.data.checkOnSave_extraArgs.clone(),
+ extra_env: self.check_on_save_extra_env(),
},
};
Some(flycheck_config)
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index 7b486744da..d511ba347a 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -1786,6 +1786,7 @@ fn run_rustfmt(
let mut command = match snap.config.rustfmt() {
RustfmtConfig::Rustfmt { extra_args, enable_range_formatting } => {
let mut cmd = process::Command::new(toolchain::rustfmt());
+ cmd.envs(snap.config.extra_env());
cmd.args(extra_args);
// try to chdir to the file so we can respect `rustfmt.toml`
// FIXME: use `rustfmt --config-path` once
@@ -1843,6 +1844,7 @@ fn run_rustfmt(
}
RustfmtConfig::CustomCommand { command, args } => {
let mut cmd = process::Command::new(command);
+ cmd.envs(snap.config.extra_env());
cmd.args(args);
cmd
}
diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs
index e47f70fff3..4cf5de46c4 100644
--- a/crates/rust-analyzer/src/reload.rs
+++ b/crates/rust-analyzer/src/reload.rs
@@ -143,6 +143,7 @@ impl GlobalState {
project_model::ProjectWorkspace::load_inline(
it.clone(),
cargo_config.target.as_deref(),
+ &cargo_config,
)
}
})
@@ -398,7 +399,11 @@ impl GlobalState {
dummy_replacements.get(crate_name).map(|v| &**v).unwrap_or_default(),
)
};
- crate_graph.extend(ws.to_crate_graph(&mut load_proc_macro, &mut load));
+ crate_graph.extend(ws.to_crate_graph(
+ &mut load_proc_macro,
+ &mut load,
+ &self.config.cargo(),
+ ));
}
crate_graph
};
diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc
index 2b02c64b66..ffae3c105c 100644
--- a/docs/user/generated_config.adoc
+++ b/docs/user/generated_config.adoc
@@ -46,6 +46,12 @@ cargo check --quiet --workspace --message-format=json --all-targets
Use `RUSTC_WRAPPER=rust-analyzer` when running build scripts to
avoid checking unnecessary things.
--
+[[rust-analyzer.cargo.extraEnv]]rust-analyzer.cargo.extraEnv (default: `{}`)::
++
+--
+Extra environment variables that will be set when running cargo, rustc
+or other commands within the workspace. Useful for setting RUSTFLAGS.
+--
[[rust-analyzer.cargo.features]]rust-analyzer.cargo.features (default: `[]`)::
+
--
@@ -93,6 +99,11 @@ Run specified `cargo check` command for diagnostics on save.
--
Extra arguments for `cargo check`.
--
+[[rust-analyzer.checkOnSave.extraEnv]]rust-analyzer.checkOnSave.extraEnv (default: `{}`)::
++
+--
+Extra environment variables that will be set when running `cargo check`.
+--
[[rust-analyzer.checkOnSave.features]]rust-analyzer.checkOnSave.features (default: `null`)::
+
--
diff --git a/editors/code/package.json b/editors/code/package.json
index cfba00d3ed..394222e73a 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -437,6 +437,11 @@
"default": true,
"type": "boolean"
},
+ "rust-analyzer.cargo.extraEnv": {
+ "markdownDescription": "Extra environment variables that will be set when running cargo, rustc\nor other commands within the workspace. Useful for setting RUSTFLAGS.",
+ "default": {},
+ "type": "object"
+ },
"rust-analyzer.cargo.features": {
"markdownDescription": "List of features to activate.\n\nSet this to `\"all\"` to pass `--all-features` to cargo.",
"default": [],
@@ -509,6 +514,11 @@
"type": "string"
}
},
+ "rust-analyzer.checkOnSave.extraEnv": {
+ "markdownDescription": "Extra environment variables that will be set when running `cargo check`.",
+ "default": {},
+ "type": "object"
+ },
"rust-analyzer.checkOnSave.features": {
"markdownDescription": "List of features to activate. Defaults to\n`#rust-analyzer.cargo.features#`.\n\nSet to `\"all\"` to pass `--all-features` to Cargo.",
"default": null,