Skip to content

Commit 60b4187

Browse files
committed
feat: Support passing multiple targets to cargo (for Rust 1.64.0+)
1 parent 499c6f6 commit 60b4187

File tree

6 files changed

+58
-35
lines changed

6 files changed

+58
-35
lines changed

crates/flycheck/src/lib.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pub use cargo_metadata::diagnostic::{
2525
pub enum FlycheckConfig {
2626
CargoCommand {
2727
command: String,
28-
target_triple: Option<String>,
28+
target_triples: Vec<String>,
2929
all_targets: bool,
3030
no_default_features: bool,
3131
all_features: bool,
@@ -253,7 +253,7 @@ impl FlycheckActor {
253253
let mut cmd = match &self.config {
254254
FlycheckConfig::CargoCommand {
255255
command,
256-
target_triple,
256+
target_triples,
257257
no_default_features,
258258
all_targets,
259259
all_features,
@@ -267,7 +267,7 @@ impl FlycheckActor {
267267
cmd.args(&["--workspace", "--message-format=json", "--manifest-path"])
268268
.arg(self.workspace_root.join("Cargo.toml").as_os_str());
269269

270-
if let Some(target) = target_triple {
270+
for target in target_triples {
271271
cmd.args(&["--target", target.as_str()]);
272272
}
273273
if *all_targets {

crates/project-model/src/build_scripts.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ impl WorkspaceBuildScripts {
5252
cmd.args(&["check", "--quiet", "--workspace", "--message-format=json"]);
5353

5454
// --all-targets includes tests, benches and examples in addition to the
55-
// default lib and bins. This is an independent concept from the --targets
55+
// default lib and bins. This is an independent concept from the --target
5656
// flag below.
5757
cmd.arg("--all-targets");
5858

crates/project-model/src/cargo_workspace.rs

+36-14
Original file line numberDiff line numberDiff line change
@@ -269,11 +269,7 @@ impl CargoWorkspace {
269269
config: &CargoConfig,
270270
progress: &dyn Fn(String),
271271
) -> Result<cargo_metadata::Metadata> {
272-
let target = config
273-
.target
274-
.clone()
275-
.or_else(|| cargo_config_build_target(cargo_toml, &config.extra_env))
276-
.or_else(|| rustc_discover_host_triple(cargo_toml, &config.extra_env));
272+
let targets = find_list_of_build_targets(config, cargo_toml);
277273

278274
let mut meta = MetadataCommand::new();
279275
meta.cargo_path(toolchain::cargo());
@@ -295,8 +291,12 @@ impl CargoWorkspace {
295291
}
296292
meta.current_dir(current_dir.as_os_str());
297293

298-
if let Some(target) = target {
299-
meta.other_options(vec![String::from("--filter-platform"), target]);
294+
if !targets.is_empty() {
295+
let other_options: Vec<_> = targets
296+
.into_iter()
297+
.flat_map(|target| ["--filter-platform".to_string(), target])
298+
.collect();
299+
meta.other_options(other_options);
300300
}
301301

302302
// FIXME: Fetching metadata is a slow process, as it might require
@@ -466,6 +466,19 @@ impl CargoWorkspace {
466466
}
467467
}
468468

469+
fn find_list_of_build_targets(config: &CargoConfig, cargo_toml: &ManifestPath) -> Vec<String> {
470+
if let Some(target) = &config.target {
471+
return [target.into()].to_vec();
472+
}
473+
474+
let build_targets = cargo_config_build_target(cargo_toml, &config.extra_env);
475+
if !build_targets.is_empty() {
476+
return build_targets;
477+
}
478+
479+
rustc_discover_host_triple(cargo_toml, &config.extra_env).into_iter().collect()
480+
}
481+
469482
fn rustc_discover_host_triple(
470483
cargo_toml: &ManifestPath,
471484
extra_env: &FxHashMap<String, String>,
@@ -496,20 +509,29 @@ fn rustc_discover_host_triple(
496509
fn cargo_config_build_target(
497510
cargo_toml: &ManifestPath,
498511
extra_env: &FxHashMap<String, String>,
499-
) -> Option<String> {
512+
) -> Vec<String> {
500513
let mut cargo_config = Command::new(toolchain::cargo());
501514
cargo_config.envs(extra_env);
502515
cargo_config
503516
.current_dir(cargo_toml.parent())
504517
.args(&["-Z", "unstable-options", "config", "get", "build.target"])
505518
.env("RUSTC_BOOTSTRAP", "1");
506519
// if successful we receive `build.target = "target-triple"`
520+
// or `build.target = ["<target 1>", ..]`
507521
tracing::debug!("Discovering cargo config target by {:?}", cargo_config);
508-
match utf8_stdout(cargo_config) {
509-
Ok(stdout) => stdout
510-
.strip_prefix("build.target = \"")
511-
.and_then(|stdout| stdout.strip_suffix('"'))
512-
.map(ToOwned::to_owned),
513-
Err(_) => None,
522+
utf8_stdout(cargo_config).map(parse_output_cargo_config_build_target).unwrap_or_default()
523+
}
524+
525+
fn parse_output_cargo_config_build_target(stdout: String) -> Vec<String> {
526+
let trimmed = stdout.trim_start_matches("build.target = ").trim_matches('"');
527+
528+
if !trimmed.starts_with('[') {
529+
return [trimmed.to_string()].to_vec();
530+
}
531+
532+
let res = serde_json::from_str(trimmed);
533+
if let Err(e) = &res {
534+
tracing::warn!("Failed to parse `build.target` as an array of target: {}`", e);
514535
}
536+
res.unwrap_or_default()
515537
}

crates/rust-analyzer/src/config.rs

+9-8
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ config_data! {
9797
/// Internal config for debugging, disables loading of sysroot crates.
9898
cargo_noSysroot: bool = "false",
9999
/// Compilation target override (target triple).
100+
// FIXME(@poliorcetics): move to multiple targets here too, but this will need more work
101+
// than `checkOnSave_target`
100102
cargo_target: Option<String> = "null",
101103
/// Unsets `#[cfg(test)]` for the specified crates.
102104
cargo_unsetTest: Vec<String> = "[\"core\"]",
@@ -139,9 +141,9 @@ config_data! {
139141
/// ```
140142
/// .
141143
checkOnSave_overrideCommand: Option<Vec<String>> = "null",
142-
/// Check for a specific target. Defaults to
143-
/// `#rust-analyzer.cargo.target#`.
144-
checkOnSave_target: Option<String> = "null",
144+
/// Check for specific targets. Defaults to
145+
/// `#rust-analyzer.cargo.targets#`.
146+
checkOnSave_target: Vec<String> = "[]",
145147

146148
/// Toggles the additional completions that automatically add imports when completed.
147149
/// Note that your client must specify the `additionalTextEdits` LSP client capability to truly have this feature enabled.
@@ -1077,11 +1079,10 @@ impl Config {
10771079
}
10781080
Some(_) | None => FlycheckConfig::CargoCommand {
10791081
command: self.data.checkOnSave_command.clone(),
1080-
target_triple: self
1081-
.data
1082-
.checkOnSave_target
1083-
.clone()
1084-
.or_else(|| self.data.cargo_target.clone()),
1082+
target_triples: match self.data.checkOnSave_target.is_empty() {
1083+
false => self.data.checkOnSave_target.clone(),
1084+
true => self.data.cargo_target.clone().into_iter().collect(),
1085+
},
10851086
all_targets: self.data.checkOnSave_allTargets,
10861087
no_default_features: self
10871088
.data

docs/user/generated_config.adoc

+3-3
Original file line numberDiff line numberDiff line change
@@ -141,11 +141,11 @@ cargo check --workspace --message-format=json --all-targets
141141
```
142142
.
143143
--
144-
[[rust-analyzer.checkOnSave.target]]rust-analyzer.checkOnSave.target (default: `null`)::
144+
[[rust-analyzer.checkOnSave.target]]rust-analyzer.checkOnSave.target (default: `[]`)::
145145
+
146146
--
147-
Check for a specific target. Defaults to
148-
`#rust-analyzer.cargo.target#`.
147+
Check for specific targets. Defaults to
148+
`#rust-analyzer.cargo.targets#`.
149149
--
150150
[[rust-analyzer.completion.autoimport.enable]]rust-analyzer.completion.autoimport.enable (default: `true`)::
151151
+

editors/code/package.json

+6-6
Original file line numberDiff line numberDiff line change
@@ -563,12 +563,12 @@
563563
}
564564
},
565565
"rust-analyzer.checkOnSave.target": {
566-
"markdownDescription": "Check for a specific target. Defaults to\n`#rust-analyzer.cargo.target#`.",
567-
"default": null,
568-
"type": [
569-
"null",
570-
"string"
571-
]
566+
"markdownDescription": "Check for specific targets. Defaults to\n`#rust-analyzer.cargo.targets#`.",
567+
"default": [],
568+
"type": "array",
569+
"items": {
570+
"type": "string"
571+
}
572572
},
573573
"rust-analyzer.completion.autoimport.enable": {
574574
"markdownDescription": "Toggles the additional completions that automatically add imports when completed.\nNote that your client must specify the `additionalTextEdits` LSP client capability to truly have this feature enabled.",

0 commit comments

Comments
 (0)