Skip to content

Commit a02a219

Browse files
committed
Auto merge of #16554 - Veykril:proc-macro-cargo-config-env, r=Veykril
fix: Pass .cargo/config.toml env vars to proc-macro server Fixes #13976
2 parents 2c05da1 + a981db5 commit a02a219

File tree

6 files changed

+83
-13
lines changed

6 files changed

+83
-13
lines changed

crates/load-cargo/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,9 @@ pub fn load_workspace(
6767
let proc_macro_server = match &load_config.with_proc_macro_server {
6868
ProcMacroServerChoice::Sysroot => ws
6969
.find_sysroot_proc_macro_srv()
70-
.and_then(|it| ProcMacroServer::spawn(it).map_err(Into::into)),
70+
.and_then(|it| ProcMacroServer::spawn(it, extra_env).map_err(Into::into)),
7171
ProcMacroServerChoice::Explicit(path) => {
72-
ProcMacroServer::spawn(path.clone()).map_err(Into::into)
72+
ProcMacroServer::spawn(path.clone(), extra_env).map_err(Into::into)
7373
}
7474
ProcMacroServerChoice::None => Err(anyhow::format_err!("proc macro server disabled")),
7575
};

crates/proc-macro-api/src/lib.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ mod version;
1313

1414
use indexmap::IndexSet;
1515
use paths::AbsPathBuf;
16+
use rustc_hash::FxHashMap;
1617
use span::Span;
1718
use std::{
1819
fmt, io,
@@ -107,8 +108,11 @@ pub struct MacroPanic {
107108

108109
impl ProcMacroServer {
109110
/// Spawns an external process as the proc macro server and returns a client connected to it.
110-
pub fn spawn(process_path: AbsPathBuf) -> io::Result<ProcMacroServer> {
111-
let process = ProcMacroProcessSrv::run(process_path)?;
111+
pub fn spawn(
112+
process_path: AbsPathBuf,
113+
env: &FxHashMap<String, String>,
114+
) -> io::Result<ProcMacroServer> {
115+
let process = ProcMacroProcessSrv::run(process_path, env)?;
112116
Ok(ProcMacroServer { process: Arc::new(Mutex::new(process)) })
113117
}
114118

crates/proc-macro-api/src/process.rs

+19-6
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use std::{
77
};
88

99
use paths::{AbsPath, AbsPathBuf};
10+
use rustc_hash::FxHashMap;
1011
use stdx::JodChild;
1112

1213
use crate::{
@@ -26,9 +27,12 @@ pub(crate) struct ProcMacroProcessSrv {
2627
}
2728

2829
impl ProcMacroProcessSrv {
29-
pub(crate) fn run(process_path: AbsPathBuf) -> io::Result<ProcMacroProcessSrv> {
30+
pub(crate) fn run(
31+
process_path: AbsPathBuf,
32+
env: &FxHashMap<String, String>,
33+
) -> io::Result<ProcMacroProcessSrv> {
3034
let create_srv = |null_stderr| {
31-
let mut process = Process::run(process_path.clone(), null_stderr)?;
35+
let mut process = Process::run(process_path.clone(), env, null_stderr)?;
3236
let (stdin, stdout) = process.stdio().expect("couldn't access child stdio");
3337

3438
io::Result::Ok(ProcMacroProcessSrv {
@@ -147,8 +151,12 @@ struct Process {
147151
}
148152

149153
impl Process {
150-
fn run(path: AbsPathBuf, null_stderr: bool) -> io::Result<Process> {
151-
let child = JodChild(mk_child(&path, null_stderr)?);
154+
fn run(
155+
path: AbsPathBuf,
156+
env: &FxHashMap<String, String>,
157+
null_stderr: bool,
158+
) -> io::Result<Process> {
159+
let child = JodChild(mk_child(&path, env, null_stderr)?);
152160
Ok(Process { child })
153161
}
154162

@@ -161,9 +169,14 @@ impl Process {
161169
}
162170
}
163171

164-
fn mk_child(path: &AbsPath, null_stderr: bool) -> io::Result<Child> {
172+
fn mk_child(
173+
path: &AbsPath,
174+
env: &FxHashMap<String, String>,
175+
null_stderr: bool,
176+
) -> io::Result<Child> {
165177
let mut cmd = Command::new(path.as_os_str());
166-
cmd.env("RUST_ANALYZER_INTERNALS_DO_NOT_USE", "this is unstable")
178+
cmd.envs(env)
179+
.env("RUST_ANALYZER_INTERNALS_DO_NOT_USE", "this is unstable")
167180
.stdin(Stdio::piped())
168181
.stdout(Stdio::piped())
169182
.stderr(if null_stderr { Stdio::null() } else { Stdio::inherit() });

crates/project-model/src/tests.rs

+3
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ fn load_cargo_with_overrides(
3434
cfg_overrides,
3535
toolchain: None,
3636
target_layout: Err("target_data_layout not loaded".into()),
37+
cargo_config_extra_env: Default::default(),
3738
};
3839
to_crate_graph(project_workspace)
3940
}
@@ -53,6 +54,7 @@ fn load_cargo_with_fake_sysroot(
5354
cfg_overrides: Default::default(),
5455
toolchain: None,
5556
target_layout: Err("target_data_layout not loaded".into()),
57+
cargo_config_extra_env: Default::default(),
5658
};
5759
project_workspace.to_crate_graph(
5860
&mut {
@@ -332,6 +334,7 @@ fn smoke_test_real_sysroot_cargo() {
332334
cfg_overrides: Default::default(),
333335
toolchain: None,
334336
target_layout: Err("target_data_layout not loaded".into()),
337+
cargo_config_extra_env: Default::default(),
335338
};
336339
project_workspace.to_crate_graph(
337340
&mut {

crates/project-model/src/workspace.rs

+41-2
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ pub enum ProjectWorkspace {
7373
cfg_overrides: CfgOverrides,
7474
toolchain: Option<Version>,
7575
target_layout: Result<String, String>,
76+
cargo_config_extra_env: FxHashMap<String, String>,
7677
},
7778
/// Project workspace was manually specified using a `rust-project.json` file.
7879
Json {
@@ -115,7 +116,8 @@ impl fmt::Debug for ProjectWorkspace {
115116
rustc_cfg,
116117
cfg_overrides,
117118
toolchain,
118-
target_layout: data_layout,
119+
target_layout,
120+
cargo_config_extra_env,
119121
} => f
120122
.debug_struct("Cargo")
121123
.field("root", &cargo.workspace_root().file_name())
@@ -128,7 +130,8 @@ impl fmt::Debug for ProjectWorkspace {
128130
.field("n_rustc_cfg", &rustc_cfg.len())
129131
.field("n_cfg_overrides", &cfg_overrides.len())
130132
.field("toolchain", &toolchain)
131-
.field("data_layout", &data_layout)
133+
.field("data_layout", &target_layout)
134+
.field("cargo_config_extra_env", &cargo_config_extra_env)
132135
.finish(),
133136
ProjectWorkspace::Json {
134137
project,
@@ -320,6 +323,8 @@ impl ProjectWorkspace {
320323
})?;
321324
let cargo = CargoWorkspace::new(meta);
322325

326+
let cargo_config_extra_env =
327+
cargo_config_env(cargo_toml, &config.extra_env, sysroot_ref);
323328
ProjectWorkspace::Cargo {
324329
cargo,
325330
build_scripts: WorkspaceBuildScripts::default(),
@@ -329,6 +334,7 @@ impl ProjectWorkspace {
329334
cfg_overrides,
330335
toolchain,
331336
target_layout: data_layout.map_err(|it| it.to_string()),
337+
cargo_config_extra_env,
332338
}
333339
}
334340
};
@@ -589,6 +595,7 @@ impl ProjectWorkspace {
589595
build_scripts,
590596
toolchain: _,
591597
target_layout: _,
598+
cargo_config_extra_env: _,
592599
} => {
593600
cargo
594601
.packages()
@@ -700,6 +707,7 @@ impl ProjectWorkspace {
700707
build_scripts,
701708
toolchain,
702709
target_layout,
710+
cargo_config_extra_env: _,
703711
} => cargo_to_crate_graph(
704712
load,
705713
rustc.as_ref().map(|a| a.as_ref()).ok(),
@@ -742,6 +750,7 @@ impl ProjectWorkspace {
742750
rustc_cfg,
743751
cfg_overrides,
744752
toolchain,
753+
cargo_config_extra_env,
745754
build_scripts: _,
746755
target_layout: _,
747756
},
@@ -752,6 +761,7 @@ impl ProjectWorkspace {
752761
rustc_cfg: o_rustc_cfg,
753762
cfg_overrides: o_cfg_overrides,
754763
toolchain: o_toolchain,
764+
cargo_config_extra_env: o_cargo_config_extra_env,
755765
build_scripts: _,
756766
target_layout: _,
757767
},
@@ -762,6 +772,7 @@ impl ProjectWorkspace {
762772
&& cfg_overrides == o_cfg_overrides
763773
&& toolchain == o_toolchain
764774
&& sysroot == o_sysroot
775+
&& cargo_config_extra_env == o_cargo_config_extra_env
765776
}
766777
(
767778
Self::Json { project, sysroot, rustc_cfg, toolchain, target_layout: _ },
@@ -1598,3 +1609,31 @@ fn create_cfg_options(rustc_cfg: Vec<CfgFlag>) -> CfgOptions {
15981609
cfg_options.insert_atom("debug_assertions".into());
15991610
cfg_options
16001611
}
1612+
1613+
fn cargo_config_env(
1614+
cargo_toml: &ManifestPath,
1615+
extra_env: &FxHashMap<String, String>,
1616+
sysroot: Option<&Sysroot>,
1617+
) -> FxHashMap<String, String> {
1618+
let Ok(program) = Sysroot::discover_tool(sysroot, toolchain::Tool::Cargo) else {
1619+
return Default::default();
1620+
};
1621+
let mut cargo_config = Command::new(program);
1622+
cargo_config.envs(extra_env);
1623+
cargo_config
1624+
.current_dir(cargo_toml.parent())
1625+
.args(["-Z", "unstable-options", "config", "get", "env"])
1626+
.env("RUSTC_BOOTSTRAP", "1");
1627+
// if successful we receive `env.key.value = "value" per entry
1628+
tracing::debug!("Discovering cargo config env by {:?}", cargo_config);
1629+
utf8_stdout(cargo_config).map(parse_output_cargo_config_env).unwrap_or_default()
1630+
}
1631+
1632+
fn parse_output_cargo_config_env(stdout: String) -> FxHashMap<String, String> {
1633+
stdout
1634+
.lines()
1635+
.filter_map(|l| l.strip_prefix("env."))
1636+
.filter_map(|l| l.split_once(".value = "))
1637+
.map(|(key, value)| (key.to_owned(), value.trim_matches('"').to_owned()))
1638+
.collect()
1639+
}

crates/rust-analyzer/src/reload.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -468,8 +468,19 @@ impl GlobalState {
468468
None => ws.find_sysroot_proc_macro_srv()?,
469469
};
470470

471+
let env = match ws {
472+
ProjectWorkspace::Cargo { cargo_config_extra_env, .. } => {
473+
cargo_config_extra_env
474+
.iter()
475+
.chain(self.config.extra_env())
476+
.map(|(a, b)| (a.clone(), b.clone()))
477+
.collect()
478+
}
479+
_ => Default::default(),
480+
};
471481
tracing::info!("Using proc-macro server at {path}");
472-
ProcMacroServer::spawn(path.clone()).map_err(|err| {
482+
483+
ProcMacroServer::spawn(path.clone(), &env).map_err(|err| {
473484
tracing::error!(
474485
"Failed to run proc-macro server from path {path}, error: {err:?}",
475486
);

0 commit comments

Comments
 (0)