Auto merge of #16554 - Veykril:proc-macro-cargo-config-env, r=Veykril
fix: Pass .cargo/config.toml env vars to proc-macro server Fixes https://github.com/rust-lang/rust-analyzer/issues/13976
This commit is contained in:
commit
a02a219773
@ -67,9 +67,9 @@ pub fn load_workspace(
|
|||||||
let proc_macro_server = match &load_config.with_proc_macro_server {
|
let proc_macro_server = match &load_config.with_proc_macro_server {
|
||||||
ProcMacroServerChoice::Sysroot => ws
|
ProcMacroServerChoice::Sysroot => ws
|
||||||
.find_sysroot_proc_macro_srv()
|
.find_sysroot_proc_macro_srv()
|
||||||
.and_then(|it| ProcMacroServer::spawn(it).map_err(Into::into)),
|
.and_then(|it| ProcMacroServer::spawn(it, extra_env).map_err(Into::into)),
|
||||||
ProcMacroServerChoice::Explicit(path) => {
|
ProcMacroServerChoice::Explicit(path) => {
|
||||||
ProcMacroServer::spawn(path.clone()).map_err(Into::into)
|
ProcMacroServer::spawn(path.clone(), extra_env).map_err(Into::into)
|
||||||
}
|
}
|
||||||
ProcMacroServerChoice::None => Err(anyhow::format_err!("proc macro server disabled")),
|
ProcMacroServerChoice::None => Err(anyhow::format_err!("proc macro server disabled")),
|
||||||
};
|
};
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
use indexmap::IndexSet;
|
use indexmap::IndexSet;
|
||||||
use paths::AbsPathBuf;
|
use paths::AbsPathBuf;
|
||||||
|
use rustc_hash::FxHashMap;
|
||||||
use span::Span;
|
use span::Span;
|
||||||
use std::{
|
use std::{
|
||||||
fmt, io,
|
fmt, io,
|
||||||
@ -107,8 +108,11 @@ pub struct MacroPanic {
|
|||||||
|
|
||||||
impl ProcMacroServer {
|
impl ProcMacroServer {
|
||||||
/// Spawns an external process as the proc macro server and returns a client connected to it.
|
/// Spawns an external process as the proc macro server and returns a client connected to it.
|
||||||
pub fn spawn(process_path: AbsPathBuf) -> io::Result<ProcMacroServer> {
|
pub fn spawn(
|
||||||
let process = ProcMacroProcessSrv::run(process_path)?;
|
process_path: AbsPathBuf,
|
||||||
|
env: &FxHashMap<String, String>,
|
||||||
|
) -> io::Result<ProcMacroServer> {
|
||||||
|
let process = ProcMacroProcessSrv::run(process_path, env)?;
|
||||||
Ok(ProcMacroServer { process: Arc::new(Mutex::new(process)) })
|
Ok(ProcMacroServer { process: Arc::new(Mutex::new(process)) })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
use paths::{AbsPath, AbsPathBuf};
|
use paths::{AbsPath, AbsPathBuf};
|
||||||
|
use rustc_hash::FxHashMap;
|
||||||
use stdx::JodChild;
|
use stdx::JodChild;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -26,9 +27,12 @@ pub(crate) struct ProcMacroProcessSrv {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ProcMacroProcessSrv {
|
impl ProcMacroProcessSrv {
|
||||||
pub(crate) fn run(process_path: AbsPathBuf) -> io::Result<ProcMacroProcessSrv> {
|
pub(crate) fn run(
|
||||||
|
process_path: AbsPathBuf,
|
||||||
|
env: &FxHashMap<String, String>,
|
||||||
|
) -> io::Result<ProcMacroProcessSrv> {
|
||||||
let create_srv = |null_stderr| {
|
let create_srv = |null_stderr| {
|
||||||
let mut process = Process::run(process_path.clone(), null_stderr)?;
|
let mut process = Process::run(process_path.clone(), env, null_stderr)?;
|
||||||
let (stdin, stdout) = process.stdio().expect("couldn't access child stdio");
|
let (stdin, stdout) = process.stdio().expect("couldn't access child stdio");
|
||||||
|
|
||||||
io::Result::Ok(ProcMacroProcessSrv {
|
io::Result::Ok(ProcMacroProcessSrv {
|
||||||
@ -147,8 +151,12 @@ struct Process {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Process {
|
impl Process {
|
||||||
fn run(path: AbsPathBuf, null_stderr: bool) -> io::Result<Process> {
|
fn run(
|
||||||
let child = JodChild(mk_child(&path, null_stderr)?);
|
path: AbsPathBuf,
|
||||||
|
env: &FxHashMap<String, String>,
|
||||||
|
null_stderr: bool,
|
||||||
|
) -> io::Result<Process> {
|
||||||
|
let child = JodChild(mk_child(&path, env, null_stderr)?);
|
||||||
Ok(Process { child })
|
Ok(Process { child })
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,9 +169,14 @@ fn stdio(&mut self) -> Option<(ChildStdin, BufReader<ChildStdout>)> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mk_child(path: &AbsPath, null_stderr: bool) -> io::Result<Child> {
|
fn mk_child(
|
||||||
|
path: &AbsPath,
|
||||||
|
env: &FxHashMap<String, String>,
|
||||||
|
null_stderr: bool,
|
||||||
|
) -> io::Result<Child> {
|
||||||
let mut cmd = Command::new(path.as_os_str());
|
let mut cmd = Command::new(path.as_os_str());
|
||||||
cmd.env("RUST_ANALYZER_INTERNALS_DO_NOT_USE", "this is unstable")
|
cmd.envs(env)
|
||||||
|
.env("RUST_ANALYZER_INTERNALS_DO_NOT_USE", "this is unstable")
|
||||||
.stdin(Stdio::piped())
|
.stdin(Stdio::piped())
|
||||||
.stdout(Stdio::piped())
|
.stdout(Stdio::piped())
|
||||||
.stderr(if null_stderr { Stdio::null() } else { Stdio::inherit() });
|
.stderr(if null_stderr { Stdio::null() } else { Stdio::inherit() });
|
||||||
|
@ -34,6 +34,7 @@ fn load_cargo_with_overrides(
|
|||||||
cfg_overrides,
|
cfg_overrides,
|
||||||
toolchain: None,
|
toolchain: None,
|
||||||
target_layout: Err("target_data_layout not loaded".into()),
|
target_layout: Err("target_data_layout not loaded".into()),
|
||||||
|
cargo_config_extra_env: Default::default(),
|
||||||
};
|
};
|
||||||
to_crate_graph(project_workspace)
|
to_crate_graph(project_workspace)
|
||||||
}
|
}
|
||||||
@ -53,6 +54,7 @@ fn load_cargo_with_fake_sysroot(
|
|||||||
cfg_overrides: Default::default(),
|
cfg_overrides: Default::default(),
|
||||||
toolchain: None,
|
toolchain: None,
|
||||||
target_layout: Err("target_data_layout not loaded".into()),
|
target_layout: Err("target_data_layout not loaded".into()),
|
||||||
|
cargo_config_extra_env: Default::default(),
|
||||||
};
|
};
|
||||||
project_workspace.to_crate_graph(
|
project_workspace.to_crate_graph(
|
||||||
&mut {
|
&mut {
|
||||||
@ -332,6 +334,7 @@ fn smoke_test_real_sysroot_cargo() {
|
|||||||
cfg_overrides: Default::default(),
|
cfg_overrides: Default::default(),
|
||||||
toolchain: None,
|
toolchain: None,
|
||||||
target_layout: Err("target_data_layout not loaded".into()),
|
target_layout: Err("target_data_layout not loaded".into()),
|
||||||
|
cargo_config_extra_env: Default::default(),
|
||||||
};
|
};
|
||||||
project_workspace.to_crate_graph(
|
project_workspace.to_crate_graph(
|
||||||
&mut {
|
&mut {
|
||||||
|
@ -73,6 +73,7 @@ pub enum ProjectWorkspace {
|
|||||||
cfg_overrides: CfgOverrides,
|
cfg_overrides: CfgOverrides,
|
||||||
toolchain: Option<Version>,
|
toolchain: Option<Version>,
|
||||||
target_layout: Result<String, String>,
|
target_layout: Result<String, String>,
|
||||||
|
cargo_config_extra_env: FxHashMap<String, String>,
|
||||||
},
|
},
|
||||||
/// Project workspace was manually specified using a `rust-project.json` file.
|
/// Project workspace was manually specified using a `rust-project.json` file.
|
||||||
Json {
|
Json {
|
||||||
@ -115,7 +116,8 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|||||||
rustc_cfg,
|
rustc_cfg,
|
||||||
cfg_overrides,
|
cfg_overrides,
|
||||||
toolchain,
|
toolchain,
|
||||||
target_layout: data_layout,
|
target_layout,
|
||||||
|
cargo_config_extra_env,
|
||||||
} => f
|
} => f
|
||||||
.debug_struct("Cargo")
|
.debug_struct("Cargo")
|
||||||
.field("root", &cargo.workspace_root().file_name())
|
.field("root", &cargo.workspace_root().file_name())
|
||||||
@ -128,7 +130,8 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|||||||
.field("n_rustc_cfg", &rustc_cfg.len())
|
.field("n_rustc_cfg", &rustc_cfg.len())
|
||||||
.field("n_cfg_overrides", &cfg_overrides.len())
|
.field("n_cfg_overrides", &cfg_overrides.len())
|
||||||
.field("toolchain", &toolchain)
|
.field("toolchain", &toolchain)
|
||||||
.field("data_layout", &data_layout)
|
.field("data_layout", &target_layout)
|
||||||
|
.field("cargo_config_extra_env", &cargo_config_extra_env)
|
||||||
.finish(),
|
.finish(),
|
||||||
ProjectWorkspace::Json {
|
ProjectWorkspace::Json {
|
||||||
project,
|
project,
|
||||||
@ -320,6 +323,8 @@ fn load_inner(
|
|||||||
})?;
|
})?;
|
||||||
let cargo = CargoWorkspace::new(meta);
|
let cargo = CargoWorkspace::new(meta);
|
||||||
|
|
||||||
|
let cargo_config_extra_env =
|
||||||
|
cargo_config_env(cargo_toml, &config.extra_env, sysroot_ref);
|
||||||
ProjectWorkspace::Cargo {
|
ProjectWorkspace::Cargo {
|
||||||
cargo,
|
cargo,
|
||||||
build_scripts: WorkspaceBuildScripts::default(),
|
build_scripts: WorkspaceBuildScripts::default(),
|
||||||
@ -329,6 +334,7 @@ fn load_inner(
|
|||||||
cfg_overrides,
|
cfg_overrides,
|
||||||
toolchain,
|
toolchain,
|
||||||
target_layout: data_layout.map_err(|it| it.to_string()),
|
target_layout: data_layout.map_err(|it| it.to_string()),
|
||||||
|
cargo_config_extra_env,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -589,6 +595,7 @@ pub fn to_roots(&self) -> Vec<PackageRoot> {
|
|||||||
build_scripts,
|
build_scripts,
|
||||||
toolchain: _,
|
toolchain: _,
|
||||||
target_layout: _,
|
target_layout: _,
|
||||||
|
cargo_config_extra_env: _,
|
||||||
} => {
|
} => {
|
||||||
cargo
|
cargo
|
||||||
.packages()
|
.packages()
|
||||||
@ -700,6 +707,7 @@ pub fn to_crate_graph(
|
|||||||
build_scripts,
|
build_scripts,
|
||||||
toolchain,
|
toolchain,
|
||||||
target_layout,
|
target_layout,
|
||||||
|
cargo_config_extra_env: _,
|
||||||
} => cargo_to_crate_graph(
|
} => cargo_to_crate_graph(
|
||||||
load,
|
load,
|
||||||
rustc.as_ref().map(|a| a.as_ref()).ok(),
|
rustc.as_ref().map(|a| a.as_ref()).ok(),
|
||||||
@ -742,6 +750,7 @@ pub fn eq_ignore_build_data(&self, other: &Self) -> bool {
|
|||||||
rustc_cfg,
|
rustc_cfg,
|
||||||
cfg_overrides,
|
cfg_overrides,
|
||||||
toolchain,
|
toolchain,
|
||||||
|
cargo_config_extra_env,
|
||||||
build_scripts: _,
|
build_scripts: _,
|
||||||
target_layout: _,
|
target_layout: _,
|
||||||
},
|
},
|
||||||
@ -752,6 +761,7 @@ pub fn eq_ignore_build_data(&self, other: &Self) -> bool {
|
|||||||
rustc_cfg: o_rustc_cfg,
|
rustc_cfg: o_rustc_cfg,
|
||||||
cfg_overrides: o_cfg_overrides,
|
cfg_overrides: o_cfg_overrides,
|
||||||
toolchain: o_toolchain,
|
toolchain: o_toolchain,
|
||||||
|
cargo_config_extra_env: o_cargo_config_extra_env,
|
||||||
build_scripts: _,
|
build_scripts: _,
|
||||||
target_layout: _,
|
target_layout: _,
|
||||||
},
|
},
|
||||||
@ -762,6 +772,7 @@ pub fn eq_ignore_build_data(&self, other: &Self) -> bool {
|
|||||||
&& cfg_overrides == o_cfg_overrides
|
&& cfg_overrides == o_cfg_overrides
|
||||||
&& toolchain == o_toolchain
|
&& toolchain == o_toolchain
|
||||||
&& sysroot == o_sysroot
|
&& sysroot == o_sysroot
|
||||||
|
&& cargo_config_extra_env == o_cargo_config_extra_env
|
||||||
}
|
}
|
||||||
(
|
(
|
||||||
Self::Json { project, sysroot, rustc_cfg, toolchain, target_layout: _ },
|
Self::Json { project, sysroot, rustc_cfg, toolchain, target_layout: _ },
|
||||||
@ -1598,3 +1609,31 @@ fn create_cfg_options(rustc_cfg: Vec<CfgFlag>) -> CfgOptions {
|
|||||||
cfg_options.insert_atom("debug_assertions".into());
|
cfg_options.insert_atom("debug_assertions".into());
|
||||||
cfg_options
|
cfg_options
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn cargo_config_env(
|
||||||
|
cargo_toml: &ManifestPath,
|
||||||
|
extra_env: &FxHashMap<String, String>,
|
||||||
|
sysroot: Option<&Sysroot>,
|
||||||
|
) -> FxHashMap<String, String> {
|
||||||
|
let Ok(program) = Sysroot::discover_tool(sysroot, toolchain::Tool::Cargo) else {
|
||||||
|
return Default::default();
|
||||||
|
};
|
||||||
|
let mut cargo_config = Command::new(program);
|
||||||
|
cargo_config.envs(extra_env);
|
||||||
|
cargo_config
|
||||||
|
.current_dir(cargo_toml.parent())
|
||||||
|
.args(["-Z", "unstable-options", "config", "get", "env"])
|
||||||
|
.env("RUSTC_BOOTSTRAP", "1");
|
||||||
|
// if successful we receive `env.key.value = "value" per entry
|
||||||
|
tracing::debug!("Discovering cargo config env by {:?}", cargo_config);
|
||||||
|
utf8_stdout(cargo_config).map(parse_output_cargo_config_env).unwrap_or_default()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_output_cargo_config_env(stdout: String) -> FxHashMap<String, String> {
|
||||||
|
stdout
|
||||||
|
.lines()
|
||||||
|
.filter_map(|l| l.strip_prefix("env."))
|
||||||
|
.filter_map(|l| l.split_once(".value = "))
|
||||||
|
.map(|(key, value)| (key.to_owned(), value.trim_matches('"').to_owned()))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
@ -468,8 +468,19 @@ pub(crate) fn switch_workspaces(&mut self, cause: Cause) {
|
|||||||
None => ws.find_sysroot_proc_macro_srv()?,
|
None => ws.find_sysroot_proc_macro_srv()?,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let env = match ws {
|
||||||
|
ProjectWorkspace::Cargo { cargo_config_extra_env, .. } => {
|
||||||
|
cargo_config_extra_env
|
||||||
|
.iter()
|
||||||
|
.chain(self.config.extra_env())
|
||||||
|
.map(|(a, b)| (a.clone(), b.clone()))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
_ => Default::default(),
|
||||||
|
};
|
||||||
tracing::info!("Using proc-macro server at {path}");
|
tracing::info!("Using proc-macro server at {path}");
|
||||||
ProcMacroServer::spawn(path.clone()).map_err(|err| {
|
|
||||||
|
ProcMacroServer::spawn(path.clone(), &env).map_err(|err| {
|
||||||
tracing::error!(
|
tracing::error!(
|
||||||
"Failed to run proc-macro server from path {path}, error: {err:?}",
|
"Failed to run proc-macro server from path {path}, error: {err:?}",
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user