Skip to content

Commit c407cc5

Browse files
committed
Add cargo.extraEnv setting
1 parent f64c956 commit c407cc5

18 files changed

+155
-43
lines changed

Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/flycheck/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ doctest = false
1313
crossbeam-channel = "0.5.5"
1414
tracing = "0.1.35"
1515
cargo_metadata = "0.15.0"
16+
rustc-hash = "1.1.0"
1617
serde = { version = "1.0.137", features = ["derive"] }
1718
serde_json = "1.0.81"
1819
jod-thread = "0.1.2"

crates/flycheck/src/lib.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use std::{
1212

1313
use crossbeam_channel::{never, select, unbounded, Receiver, Sender};
1414
use paths::AbsPathBuf;
15+
use rustc_hash::FxHashMap;
1516
use serde::Deserialize;
1617
use stdx::{process::streaming_output, JodChild};
1718

@@ -30,18 +31,20 @@ pub enum FlycheckConfig {
3031
all_features: bool,
3132
features: Vec<String>,
3233
extra_args: Vec<String>,
34+
extra_env: FxHashMap<String, String>,
3335
},
3436
CustomCommand {
3537
command: String,
3638
args: Vec<String>,
39+
extra_env: FxHashMap<String, String>,
3740
},
3841
}
3942

4043
impl fmt::Display for FlycheckConfig {
4144
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4245
match self {
4346
FlycheckConfig::CargoCommand { command, .. } => write!(f, "cargo {}", command),
44-
FlycheckConfig::CustomCommand { command, args } => {
47+
FlycheckConfig::CustomCommand { command, args, .. } => {
4548
write!(f, "{} {}", command, args.join(" "))
4649
}
4750
}
@@ -256,6 +259,7 @@ impl FlycheckActor {
256259
all_features,
257260
extra_args,
258261
features,
262+
extra_env,
259263
} => {
260264
let mut cmd = Command::new(toolchain::cargo());
261265
cmd.arg(command);
@@ -281,11 +285,13 @@ impl FlycheckActor {
281285
}
282286
}
283287
cmd.args(extra_args);
288+
cmd.envs(extra_env);
284289
cmd
285290
}
286-
FlycheckConfig::CustomCommand { command, args } => {
291+
FlycheckConfig::CustomCommand { command, args, extra_env } => {
287292
let mut cmd = Command::new(command);
288293
cmd.args(args);
294+
cmd.envs(extra_env);
289295
cmd
290296
}
291297
};

crates/project-model/src/build_scripts.rs

+2
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,12 @@ impl WorkspaceBuildScripts {
4343
if let Some([program, args @ ..]) = config.run_build_script_command.as_deref() {
4444
let mut cmd = Command::new(program);
4545
cmd.args(args);
46+
cmd.envs(&config.extra_env);
4647
return cmd;
4748
}
4849

4950
let mut cmd = Command::new(toolchain::cargo());
51+
cmd.envs(&config.extra_env);
5052

5153
cmd.args(&["check", "--quiet", "--workspace", "--message-format=json"]);
5254

crates/project-model/src/cargo_workspace.rs

+30-6
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
use std::iter;
44
use std::path::PathBuf;
5+
use std::str::from_utf8;
56
use std::{ops, process::Command};
67

78
use anyhow::{Context, Result};
@@ -98,6 +99,8 @@ pub struct CargoConfig {
9899
pub wrap_rustc_in_build_scripts: bool,
99100

100101
pub run_build_script_command: Option<Vec<String>>,
102+
103+
pub extra_env: FxHashMap<String, String>,
101104
}
102105

103106
impl CargoConfig {
@@ -263,8 +266,8 @@ impl CargoWorkspace {
263266
let target = config
264267
.target
265268
.clone()
266-
.or_else(|| cargo_config_build_target(cargo_toml))
267-
.or_else(|| rustc_discover_host_triple(cargo_toml));
269+
.or_else(|| cargo_config_build_target(cargo_toml, config))
270+
.or_else(|| rustc_discover_host_triple(cargo_toml, config));
268271

269272
let mut meta = MetadataCommand::new();
270273
meta.cargo_path(toolchain::cargo());
@@ -292,8 +295,27 @@ impl CargoWorkspace {
292295
// unclear whether cargo itself supports it.
293296
progress("metadata".to_string());
294297

295-
let meta =
296-
meta.exec().with_context(|| format!("Failed to run `{:?}`", meta.cargo_command()))?;
298+
fn exec_with_env(
299+
command: &cargo_metadata::MetadataCommand,
300+
extra_env: &FxHashMap<String, String>,
301+
) -> Result<cargo_metadata::Metadata, cargo_metadata::Error> {
302+
let mut command = command.cargo_command();
303+
command.envs(extra_env);
304+
let output = command.output()?;
305+
if !output.status.success() {
306+
return Err(cargo_metadata::Error::CargoMetadata {
307+
stderr: String::from_utf8(output.stderr)?,
308+
});
309+
}
310+
let stdout = from_utf8(&output.stdout)?
311+
.lines()
312+
.find(|line| line.starts_with('{'))
313+
.ok_or(cargo_metadata::Error::NoJson)?;
314+
cargo_metadata::MetadataCommand::parse(stdout)
315+
}
316+
317+
let meta = exec_with_env(&meta, &config.extra_env)
318+
.with_context(|| format!("Failed to run `{:?}`", meta.cargo_command()))?;
297319

298320
Ok(meta)
299321
}
@@ -463,8 +485,9 @@ impl CargoWorkspace {
463485
}
464486
}
465487

466-
fn rustc_discover_host_triple(cargo_toml: &ManifestPath) -> Option<String> {
488+
fn rustc_discover_host_triple(cargo_toml: &ManifestPath, config: &CargoConfig) -> Option<String> {
467489
let mut rustc = Command::new(toolchain::rustc());
490+
rustc.envs(&config.extra_env);
468491
rustc.current_dir(cargo_toml.parent()).arg("-vV");
469492
tracing::debug!("Discovering host platform by {:?}", rustc);
470493
match utf8_stdout(rustc) {
@@ -486,8 +509,9 @@ fn rustc_discover_host_triple(cargo_toml: &ManifestPath) -> Option<String> {
486509
}
487510
}
488511

489-
fn cargo_config_build_target(cargo_toml: &ManifestPath) -> Option<String> {
512+
fn cargo_config_build_target(cargo_toml: &ManifestPath, config: &CargoConfig) -> Option<String> {
490513
let mut cargo_config = Command::new(toolchain::cargo());
514+
cargo_config.envs(&config.extra_env);
491515
cargo_config
492516
.current_dir(cargo_toml.parent())
493517
.args(&["-Z", "unstable-options", "config", "get", "build.target"])

crates/project-model/src/rustc_cfg.rs

+14-4
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,13 @@ use std::process::Command;
44

55
use anyhow::Result;
66

7-
use crate::{cfg_flag::CfgFlag, utf8_stdout, ManifestPath};
7+
use crate::{cfg_flag::CfgFlag, utf8_stdout, CargoConfig, ManifestPath};
88

9-
pub(crate) fn get(cargo_toml: Option<&ManifestPath>, target: Option<&str>) -> Vec<CfgFlag> {
9+
pub(crate) fn get(
10+
cargo_toml: Option<&ManifestPath>,
11+
target: Option<&str>,
12+
config: &CargoConfig,
13+
) -> Vec<CfgFlag> {
1014
let _p = profile::span("rustc_cfg::get");
1115
let mut res = Vec::with_capacity(6 * 2 + 1);
1216

@@ -18,7 +22,7 @@ pub(crate) fn get(cargo_toml: Option<&ManifestPath>, target: Option<&str>) -> Ve
1822
}
1923
}
2024

21-
match get_rust_cfgs(cargo_toml, target) {
25+
match get_rust_cfgs(cargo_toml, target, config) {
2226
Ok(rustc_cfgs) => {
2327
tracing::debug!(
2428
"rustc cfgs found: {:?}",
@@ -35,9 +39,14 @@ pub(crate) fn get(cargo_toml: Option<&ManifestPath>, target: Option<&str>) -> Ve
3539
res
3640
}
3741

38-
fn get_rust_cfgs(cargo_toml: Option<&ManifestPath>, target: Option<&str>) -> Result<String> {
42+
fn get_rust_cfgs(
43+
cargo_toml: Option<&ManifestPath>,
44+
target: Option<&str>,
45+
config: &CargoConfig,
46+
) -> Result<String> {
3947
if let Some(cargo_toml) = cargo_toml {
4048
let mut cargo_config = Command::new(toolchain::cargo());
49+
cargo_config.envs(&config.extra_env);
4150
cargo_config
4251
.current_dir(cargo_toml.parent())
4352
.args(&["-Z", "unstable-options", "rustc", "--print", "cfg"])
@@ -52,6 +61,7 @@ fn get_rust_cfgs(cargo_toml: Option<&ManifestPath>, target: Option<&str>) -> Res
5261
}
5362
// using unstable cargo features failed, fall back to using plain rustc
5463
let mut cmd = Command::new(toolchain::rustc());
64+
cmd.envs(&config.extra_env);
5565
cmd.args(&["--print", "cfg", "-O"]);
5666
if let Some(target) = target {
5767
cmd.args(&["--target", target]);

crates/project-model/src/sysroot.rs

+12-7
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use anyhow::{format_err, Result};
1010
use la_arena::{Arena, Idx};
1111
use paths::{AbsPath, AbsPathBuf};
1212

13-
use crate::{utf8_stdout, ManifestPath};
13+
use crate::{utf8_stdout, CargoConfig, ManifestPath};
1414

1515
#[derive(Debug, Clone, Eq, PartialEq)]
1616
pub struct Sysroot {
@@ -67,18 +67,20 @@ impl Sysroot {
6767
self.crates.iter().map(|(id, _data)| id)
6868
}
6969

70-
pub fn discover(dir: &AbsPath) -> Result<Sysroot> {
70+
pub fn discover(dir: &AbsPath, config: &CargoConfig) -> Result<Sysroot> {
7171
tracing::debug!("Discovering sysroot for {}", dir.display());
72-
let sysroot_dir = discover_sysroot_dir(dir)?;
73-
let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir, dir)?;
72+
let sysroot_dir = discover_sysroot_dir(dir, config)?;
73+
let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir, dir, config)?;
7474
let res = Sysroot::load(sysroot_dir, sysroot_src_dir)?;
7575
Ok(res)
7676
}
7777

78-
pub fn discover_rustc(cargo_toml: &ManifestPath) -> Option<ManifestPath> {
78+
pub fn discover_rustc(cargo_toml: &ManifestPath, config: &CargoConfig) -> Option<ManifestPath> {
7979
tracing::debug!("Discovering rustc source for {}", cargo_toml.display());
8080
let current_dir = cargo_toml.parent();
81-
discover_sysroot_dir(current_dir).ok().and_then(|sysroot_dir| get_rustc_src(&sysroot_dir))
81+
discover_sysroot_dir(current_dir, config)
82+
.ok()
83+
.and_then(|sysroot_dir| get_rustc_src(&sysroot_dir))
8284
}
8385

8486
pub fn load(sysroot_dir: AbsPathBuf, sysroot_src_dir: AbsPathBuf) -> Result<Sysroot> {
@@ -144,8 +146,9 @@ impl Sysroot {
144146
}
145147
}
146148

147-
fn discover_sysroot_dir(current_dir: &AbsPath) -> Result<AbsPathBuf> {
149+
fn discover_sysroot_dir(current_dir: &AbsPath, config: &CargoConfig) -> Result<AbsPathBuf> {
148150
let mut rustc = Command::new(toolchain::rustc());
151+
rustc.envs(&config.extra_env);
149152
rustc.current_dir(current_dir).args(&["--print", "sysroot"]);
150153
tracing::debug!("Discovering sysroot by {:?}", rustc);
151154
let stdout = utf8_stdout(rustc)?;
@@ -155,6 +158,7 @@ fn discover_sysroot_dir(current_dir: &AbsPath) -> Result<AbsPathBuf> {
155158
fn discover_sysroot_src_dir(
156159
sysroot_path: &AbsPathBuf,
157160
current_dir: &AbsPath,
161+
config: &CargoConfig,
158162
) -> Result<AbsPathBuf> {
159163
if let Ok(path) = env::var("RUST_SRC_PATH") {
160164
let path = AbsPathBuf::try_from(path.as_str())
@@ -170,6 +174,7 @@ fn discover_sysroot_src_dir(
170174
get_rust_src(sysroot_path)
171175
.or_else(|| {
172176
let mut rustup = Command::new(toolchain::rustup());
177+
rustup.envs(&config.extra_env);
173178
rustup.current_dir(current_dir).args(&["component", "add", "rust-src"]);
174179
utf8_stdout(rustup).ok()?;
175180
get_rust_src(sysroot_path)

crates/project-model/src/tests.rs

+13-9
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ use paths::{AbsPath, AbsPathBuf};
1010
use serde::de::DeserializeOwned;
1111

1212
use crate::{
13-
CargoWorkspace, CfgOverrides, ProjectJson, ProjectJsonData, ProjectWorkspace, Sysroot,
14-
WorkspaceBuildScripts,
13+
CargoConfig, CargoWorkspace, CfgOverrides, ProjectJson, ProjectJsonData, ProjectWorkspace,
14+
Sysroot, WorkspaceBuildScripts,
1515
};
1616

1717
fn load_cargo(file: &str) -> CrateGraph {
@@ -92,13 +92,17 @@ fn rooted_project_json(data: ProjectJsonData) -> ProjectJson {
9292
}
9393

9494
fn to_crate_graph(project_workspace: ProjectWorkspace) -> CrateGraph {
95-
project_workspace.to_crate_graph(&mut |_, _| Ok(Vec::new()), &mut {
96-
let mut counter = 0;
97-
move |_path| {
98-
counter += 1;
99-
Some(FileId(counter))
100-
}
101-
})
95+
project_workspace.to_crate_graph(
96+
&mut |_, _| Ok(Vec::new()),
97+
&mut {
98+
let mut counter = 0;
99+
move |_path| {
100+
counter += 1;
101+
Some(FileId(counter))
102+
}
103+
},
104+
&CargoConfig::default(),
105+
)
102106
}
103107

104108
fn check_crate_graph(crate_graph: CrateGraph, expect: Expect) {

0 commit comments

Comments
 (0)