Skip to content

Commit 87c733c

Browse files
authored
Merge pull request #18807 from Veykril/push-vxopsoummyzx
fix: Populate cargo config env vars for crates
2 parents 88e630b + 204c8d7 commit 87c733c

File tree

7 files changed

+77
-96
lines changed

7 files changed

+77
-96
lines changed

src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use std::ops;
44
use std::str::from_utf8;
55

66
use anyhow::Context;
7+
use base_db::Env;
78
use cargo_metadata::{CargoOpt, MetadataCommand};
89
use la_arena::{Arena, Idx};
910
use paths::{AbsPath, AbsPathBuf, Utf8PathBuf};
@@ -34,6 +35,8 @@ pub struct CargoWorkspace {
3435
target_directory: AbsPathBuf,
3536
manifest_path: ManifestPath,
3637
is_virtual_workspace: bool,
38+
/// Environment variables set in the `.cargo/config` file.
39+
config_env: Env,
3740
}
3841

3942
impl ops::Index<Package> for CargoWorkspace {
@@ -395,6 +398,7 @@ impl CargoWorkspace {
395398
pub fn new(
396399
mut meta: cargo_metadata::Metadata,
397400
ws_manifest_path: ManifestPath,
401+
cargo_config_env: Env,
398402
) -> CargoWorkspace {
399403
let mut pkg_by_id = FxHashMap::default();
400404
let mut packages = Arena::default();
@@ -516,6 +520,7 @@ impl CargoWorkspace {
516520
target_directory,
517521
manifest_path: ws_manifest_path,
518522
is_virtual_workspace,
523+
config_env: cargo_config_env,
519524
}
520525
}
521526

@@ -602,4 +607,8 @@ impl CargoWorkspace {
602607
pub fn is_virtual_workspace(&self) -> bool {
603608
self.is_virtual_workspace
604609
}
610+
611+
pub fn env(&self) -> &Env {
612+
&self.config_env
613+
}
605614
}

src/tools/rust-analyzer/crates/project-model/src/env.rs

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! Cargo-like environment variables injection.
22
use base_db::Env;
3+
use paths::Utf8Path;
34
use rustc_hash::FxHashMap;
45
use toolchain::Tool;
56

@@ -73,7 +74,7 @@ pub(crate) fn cargo_config_env(
7374
manifest: &ManifestPath,
7475
extra_env: &FxHashMap<String, String>,
7576
sysroot: &Sysroot,
76-
) -> FxHashMap<String, String> {
77+
) -> Env {
7778
let mut cargo_config = sysroot.tool(Tool::Cargo, manifest.parent());
7879
cargo_config.envs(extra_env);
7980
cargo_config
@@ -85,7 +86,7 @@ pub(crate) fn cargo_config_env(
8586
// if successful we receive `env.key.value = "value" per entry
8687
tracing::debug!("Discovering cargo config env by {:?}", cargo_config);
8788
utf8_stdout(&mut cargo_config)
88-
.map(parse_output_cargo_config_env)
89+
.map(|stdout| parse_output_cargo_config_env(manifest, stdout))
8990
.inspect(|env| {
9091
tracing::debug!("Discovered cargo config env: {:?}", env);
9192
})
@@ -95,18 +96,38 @@ pub(crate) fn cargo_config_env(
9596
.unwrap_or_default()
9697
}
9798

98-
fn parse_output_cargo_config_env(stdout: String) -> FxHashMap<String, String> {
99-
stdout
100-
.lines()
101-
.filter_map(|l| l.strip_prefix("env."))
102-
.filter_map(|l| l.split_once(" = "))
103-
.filter_map(|(k, v)| {
104-
if k.contains('.') {
105-
k.strip_suffix(".value").zip(Some(v))
106-
} else {
107-
Some((k, v))
99+
fn parse_output_cargo_config_env(manifest: &ManifestPath, stdout: String) -> Env {
100+
let mut env = Env::default();
101+
let mut relatives = vec![];
102+
for (key, val) in
103+
stdout.lines().filter_map(|l| l.strip_prefix("env.")).filter_map(|l| l.split_once(" = "))
104+
{
105+
let val = val.trim_matches('"').to_owned();
106+
if let Some((key, modifier)) = key.split_once('.') {
107+
match modifier {
108+
"relative" => relatives.push((key, val)),
109+
"value" => _ = env.insert(key, val),
110+
_ => {
111+
tracing::warn!(
112+
"Unknown modifier in cargo config env: {}, expected `relative` or `value`",
113+
modifier
114+
);
115+
continue;
116+
}
108117
}
109-
})
110-
.map(|(key, value)| (key.to_owned(), value.trim_matches('"').to_owned()))
111-
.collect()
118+
} else {
119+
env.insert(key, val);
120+
}
121+
}
122+
// FIXME: The base here should be the parent of the `.cargo/config` file, not the manifest.
123+
// But cargo does not provide this information.
124+
let base = <_ as AsRef<Utf8Path>>::as_ref(manifest.parent());
125+
for (key, val) in relatives {
126+
if let Some(val) = env.get(&val) {
127+
env.insert(key, base.join(val).to_string());
128+
} else {
129+
env.insert(key, base.to_string());
130+
}
131+
}
132+
env
112133
}

src/tools/rust-analyzer/crates/project-model/src/sysroot.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@ impl Sysroot {
422422
res.packages.remove(idx);
423423
});
424424

425-
let cargo_workspace = CargoWorkspace::new(res, library_manifest);
425+
let cargo_workspace = CargoWorkspace::new(res, library_manifest, Default::default());
426426
Some(Sysroot {
427427
root: sysroot_dir.clone(),
428428
src_root: Some(sysroot_src_dir.clone()),

src/tools/rust-analyzer/crates/project-model/src/tests.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,12 @@ fn load_cargo_with_overrides(
2828
let meta: Metadata = get_test_json_file(file);
2929
let manifest_path =
3030
ManifestPath::try_from(AbsPathBuf::try_from(meta.workspace_root.clone()).unwrap()).unwrap();
31-
let cargo_workspace = CargoWorkspace::new(meta, manifest_path);
31+
let cargo_workspace = CargoWorkspace::new(meta, manifest_path, Default::default());
3232
let project_workspace = ProjectWorkspace {
3333
kind: ProjectWorkspaceKind::Cargo {
3434
cargo: cargo_workspace,
3535
build_scripts: WorkspaceBuildScripts::default(),
3636
rustc: Err(None),
37-
cargo_config_extra_env: Default::default(),
3837
error: None,
3938
set_test: true,
4039
},
@@ -228,7 +227,7 @@ fn smoke_test_real_sysroot_cargo() {
228227
let meta: Metadata = get_test_json_file("hello-world-metadata.json");
229228
let manifest_path =
230229
ManifestPath::try_from(AbsPathBuf::try_from(meta.workspace_root.clone()).unwrap()).unwrap();
231-
let cargo_workspace = CargoWorkspace::new(meta, manifest_path);
230+
let cargo_workspace = CargoWorkspace::new(meta, manifest_path, Default::default());
232231
let sysroot = Sysroot::discover(
233232
AbsPath::assert(Utf8Path::new(env!("CARGO_MANIFEST_DIR"))),
234233
&Default::default(),
@@ -240,7 +239,6 @@ fn smoke_test_real_sysroot_cargo() {
240239
cargo: cargo_workspace,
241240
build_scripts: WorkspaceBuildScripts::default(),
242241
rustc: Err(None),
243-
cargo_config_extra_env: Default::default(),
244242
error: None,
245243
set_test: true,
246244
},

src/tools/rust-analyzer/crates/project-model/src/workspace.rs

Lines changed: 25 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,6 @@ pub enum ProjectWorkspaceKind {
7878
/// The rustc workspace loaded for this workspace. An `Err(None)` means loading has been
7979
/// disabled or was otherwise not requested.
8080
rustc: Result<Box<(CargoWorkspace, WorkspaceBuildScripts)>, Option<String>>,
81-
/// Environment variables set in the `.cargo/config` file.
82-
cargo_config_extra_env: FxHashMap<String, String>,
8381
set_test: bool,
8482
},
8583
/// Project workspace was specified using a `rust-project.json` file.
@@ -99,8 +97,6 @@ pub enum ProjectWorkspaceKind {
9997
file: ManifestPath,
10098
/// Is this file a cargo script file?
10199
cargo: Option<(CargoWorkspace, WorkspaceBuildScripts, Option<Arc<anyhow::Error>>)>,
102-
/// Environment variables set in the `.cargo/config` file.
103-
cargo_config_extra_env: FxHashMap<String, String>,
104100
set_test: bool,
105101
},
106102
}
@@ -110,14 +106,7 @@ impl fmt::Debug for ProjectWorkspace {
110106
// Make sure this isn't too verbose.
111107
let Self { kind, sysroot, rustc_cfg, toolchain, target_layout, cfg_overrides } = self;
112108
match kind {
113-
ProjectWorkspaceKind::Cargo {
114-
cargo,
115-
error: _,
116-
build_scripts,
117-
rustc,
118-
cargo_config_extra_env,
119-
set_test,
120-
} => f
109+
ProjectWorkspaceKind::Cargo { cargo, error: _, build_scripts, rustc, set_test } => f
121110
.debug_struct("Cargo")
122111
.field("root", &cargo.workspace_root().file_name())
123112
.field("n_packages", &cargo.packages().len())
@@ -130,7 +119,6 @@ impl fmt::Debug for ProjectWorkspace {
130119
.field("n_cfg_overrides", &cfg_overrides.len())
131120
.field("toolchain", &toolchain)
132121
.field("data_layout", &target_layout)
133-
.field("cargo_config_extra_env", &cargo_config_extra_env)
134122
.field("set_test", set_test)
135123
.field("build_scripts", &build_scripts.error().unwrap_or("ok"))
136124
.finish(),
@@ -146,12 +134,7 @@ impl fmt::Debug for ProjectWorkspace {
146134

147135
debug_struct.finish()
148136
}
149-
ProjectWorkspaceKind::DetachedFile {
150-
file,
151-
cargo: cargo_script,
152-
cargo_config_extra_env,
153-
set_test,
154-
} => f
137+
ProjectWorkspaceKind::DetachedFile { file, cargo: cargo_script, set_test } => f
155138
.debug_struct("DetachedFiles")
156139
.field("file", &file)
157140
.field("cargo_script", &cargo_script.is_some())
@@ -161,7 +144,6 @@ impl fmt::Debug for ProjectWorkspace {
161144
.field("toolchain", &toolchain)
162145
.field("data_layout", &target_layout)
163146
.field("n_cfg_overrides", &cfg_overrides.len())
164-
.field("cargo_config_extra_env", &cargo_config_extra_env)
165147
.field("set_test", set_test)
166148
.finish(),
167149
}
@@ -289,14 +271,14 @@ impl ProjectWorkspace {
289271
progress,
290272
) {
291273
Ok((meta, _error)) => {
292-
let workspace = CargoWorkspace::new(meta, cargo_toml.clone());
293-
let buildscripts = WorkspaceBuildScripts::rustc_crates(
274+
let workspace = CargoWorkspace::new(meta, cargo_toml.clone(), Env::default());
275+
let build_scripts = WorkspaceBuildScripts::rustc_crates(
294276
&workspace,
295277
cargo_toml.parent(),
296278
&config.extra_env,
297279
&sysroot,
298280
);
299-
Ok(Box::new((workspace, buildscripts)))
281+
Ok(Box::new((workspace, build_scripts)))
300282
}
301283
Err(e) => {
302284
tracing::error!(
@@ -348,14 +330,13 @@ impl ProjectWorkspace {
348330
"Failed to read Cargo metadata from Cargo.toml file {cargo_toml}, {toolchain:?}",
349331
)
350332
})?;
351-
let cargo = CargoWorkspace::new(meta, cargo_toml.clone());
352333
let cargo_config_extra_env = cargo_config_env(cargo_toml, &config.extra_env, &sysroot);
334+
let cargo = CargoWorkspace::new(meta, cargo_toml.clone(), cargo_config_extra_env);
353335
Ok(ProjectWorkspace {
354336
kind: ProjectWorkspaceKind::Cargo {
355337
cargo,
356338
build_scripts: WorkspaceBuildScripts::default(),
357339
rustc,
358-
cargo_config_extra_env,
359340
error: error.map(Arc::new),
360341
set_test: config.set_test,
361342
},
@@ -450,19 +431,19 @@ impl ProjectWorkspace {
450431
)
451432
.ok()
452433
.map(|(ws, error)| {
434+
let cargo_config_extra_env =
435+
cargo_config_env(detached_file, &config.extra_env, &sysroot);
453436
(
454-
CargoWorkspace::new(ws, detached_file.clone()),
437+
CargoWorkspace::new(ws, detached_file.clone(), cargo_config_extra_env),
455438
WorkspaceBuildScripts::default(),
456439
error.map(Arc::new),
457440
)
458441
});
459442

460-
let cargo_config_extra_env = cargo_config_env(detached_file, &config.extra_env, &sysroot);
461443
Ok(ProjectWorkspace {
462444
kind: ProjectWorkspaceKind::DetachedFile {
463445
file: detached_file.to_owned(),
464446
cargo: cargo_script,
465-
cargo_config_extra_env,
466447
set_test: config.set_test,
467448
},
468449
sysroot,
@@ -643,14 +624,7 @@ impl ProjectWorkspace {
643624
.chain(mk_sysroot())
644625
.unique()
645626
.collect(),
646-
ProjectWorkspaceKind::Cargo {
647-
cargo,
648-
rustc,
649-
build_scripts,
650-
cargo_config_extra_env: _,
651-
error: _,
652-
set_test: _,
653-
} => {
627+
ProjectWorkspaceKind::Cargo { cargo, rustc, build_scripts, error: _, set_test: _ } => {
654628
cargo
655629
.packages()
656630
.map(|pkg| {
@@ -787,23 +761,18 @@ impl ProjectWorkspace {
787761
extra_env,
788762
cfg_overrides,
789763
),
790-
ProjectWorkspaceKind::Cargo {
791-
cargo,
792-
rustc,
793-
build_scripts,
794-
cargo_config_extra_env: _,
795-
error: _,
796-
set_test,
797-
} => cargo_to_crate_graph(
798-
load,
799-
rustc.as_ref().map(|a| a.as_ref()).ok(),
800-
cargo,
801-
sysroot,
802-
rustc_cfg.clone(),
803-
cfg_overrides,
804-
build_scripts,
805-
*set_test,
806-
),
764+
ProjectWorkspaceKind::Cargo { cargo, rustc, build_scripts, error: _, set_test } => {
765+
cargo_to_crate_graph(
766+
load,
767+
rustc.as_ref().map(|a| a.as_ref()).ok(),
768+
cargo,
769+
sysroot,
770+
rustc_cfg.clone(),
771+
cfg_overrides,
772+
build_scripts,
773+
*set_test,
774+
)
775+
}
807776
ProjectWorkspaceKind::DetachedFile { file, cargo: cargo_script, set_test, .. } => {
808777
if let Some((cargo, build_scripts, _)) = cargo_script {
809778
cargo_to_crate_graph(
@@ -848,45 +817,33 @@ impl ProjectWorkspace {
848817
ProjectWorkspaceKind::Cargo {
849818
cargo,
850819
rustc,
851-
cargo_config_extra_env,
852820
build_scripts: _,
853821
error: _,
854822
set_test: _,
855823
},
856824
ProjectWorkspaceKind::Cargo {
857825
cargo: o_cargo,
858826
rustc: o_rustc,
859-
cargo_config_extra_env: o_cargo_config_extra_env,
860827
build_scripts: _,
861828
error: _,
862829
set_test: _,
863830
},
864-
) => {
865-
cargo == o_cargo
866-
&& rustc == o_rustc
867-
&& cargo_config_extra_env == o_cargo_config_extra_env
868-
}
831+
) => cargo == o_cargo && rustc == o_rustc,
869832
(ProjectWorkspaceKind::Json(project), ProjectWorkspaceKind::Json(o_project)) => {
870833
project == o_project
871834
}
872835
(
873836
ProjectWorkspaceKind::DetachedFile {
874837
file,
875838
cargo: Some((cargo_script, _, _)),
876-
cargo_config_extra_env,
877839
set_test: _,
878840
},
879841
ProjectWorkspaceKind::DetachedFile {
880842
file: o_file,
881843
cargo: Some((o_cargo_script, _, _)),
882-
cargo_config_extra_env: o_cargo_config_extra_env,
883844
set_test: _,
884845
},
885-
) => {
886-
file == o_file
887-
&& cargo_script == o_cargo_script
888-
&& cargo_config_extra_env == o_cargo_config_extra_env
889-
}
846+
) => file == o_file && cargo_script == o_cargo_script,
890847
_ => return false,
891848
}) && sysroot == o_sysroot
892849
&& rustc_cfg == o_rustc_cfg
@@ -1402,7 +1359,7 @@ fn add_target_crate_root(
14021359
opts
14031360
};
14041361

1405-
let mut env = Env::default();
1362+
let mut env = cargo.env().clone();
14061363
inject_cargo_package_env(&mut env, pkg);
14071364
inject_cargo_env(&mut env);
14081365
inject_rustc_tool_env(&mut env, cargo, cargo_name, kind);

src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@ impl Tester {
8989
kind: ProjectWorkspaceKind::DetachedFile {
9090
file: ManifestPath::try_from(tmp_file).unwrap(),
9191
cargo: None,
92-
cargo_config_extra_env: Default::default(),
9392
set_test: true,
9493
},
9594
sysroot,

0 commit comments

Comments
 (0)