Skip to content

Commit 54efd42

Browse files
committed
feat: Support passing multiple targets to cargo (for Rust 1.64.0+)
1 parent cd01a24 commit 54efd42

File tree

6 files changed

+56
-33
lines changed

6 files changed

+56
-33
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,
@@ -262,7 +262,7 @@ impl FlycheckActor {
262262
let mut cmd = match &self.config {
263263
FlycheckConfig::CargoCommand {
264264
command,
265-
target_triple,
265+
target_triples,
266266
no_default_features,
267267
all_targets,
268268
all_features,
@@ -276,7 +276,7 @@ impl FlycheckActor {
276276
cmd.args(&["--workspace", "--message-format=json", "--manifest-path"])
277277
.arg(self.workspace_root.join("Cargo.toml").as_os_str());
278278

279-
if let Some(target) = target_triple {
279+
for target in target_triples {
280280
cmd.args(&["--target", target.as_str()]);
281281
}
282282
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
@@ -268,11 +268,7 @@ impl CargoWorkspace {
268268
config: &CargoConfig,
269269
progress: &dyn Fn(String),
270270
) -> Result<cargo_metadata::Metadata> {
271-
let target = config
272-
.target
273-
.clone()
274-
.or_else(|| cargo_config_build_target(cargo_toml, &config.extra_env))
275-
.or_else(|| rustc_discover_host_triple(cargo_toml, &config.extra_env));
271+
let targets = find_list_of_build_targets(config, cargo_toml);
276272

277273
let mut meta = MetadataCommand::new();
278274
meta.cargo_path(toolchain::cargo());
@@ -294,8 +290,12 @@ impl CargoWorkspace {
294290
}
295291
meta.current_dir(current_dir.as_os_str());
296292

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

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

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

crates/rust-analyzer/src/config.rs

+8-7
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ config_data! {
102102
/// This option does not take effect until rust-analyzer is restarted.
103103
cargo_sysroot: Option<String> = "\"discover\"",
104104
/// Compilation target override (target triple).
105+
// FIXME(@poliorcetics): move to multiple targets here too, but this will need more work
106+
// than `checkOnSave_target`
105107
cargo_target: Option<String> = "null",
106108
/// Unsets `#[cfg(test)]` for the specified crates.
107109
cargo_unsetTest: Vec<String> = "[\"core\"]",
@@ -144,9 +146,9 @@ config_data! {
144146
/// ```
145147
/// .
146148
checkOnSave_overrideCommand: Option<Vec<String>> = "null",
147-
/// Check for a specific target. Defaults to
149+
/// Check for specific targets. Defaults to
148150
/// `#rust-analyzer.cargo.target#`.
149-
checkOnSave_target: Option<String> = "null",
151+
checkOnSave_target: Vec<String> = "[]",
150152

151153
/// Toggles the additional completions that automatically add imports when completed.
152154
/// Note that your client must specify the `additionalTextEdits` LSP client capability to truly have this feature enabled.
@@ -1091,11 +1093,10 @@ impl Config {
10911093
}
10921094
Some(_) | None => FlycheckConfig::CargoCommand {
10931095
command: self.data.checkOnSave_command.clone(),
1094-
target_triple: self
1095-
.data
1096-
.checkOnSave_target
1097-
.clone()
1098-
.or_else(|| self.data.cargo_target.clone()),
1096+
target_triples: match self.data.checkOnSave_target.is_empty() {
1097+
false => self.data.checkOnSave_target.clone(),
1098+
true => self.data.cargo_target.clone().into_iter().collect(),
1099+
},
10991100
all_targets: self.data.checkOnSave_allTargets,
11001101
no_default_features: self
11011102
.data

docs/user/generated_config.adoc

+2-2
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,10 @@ cargo check --workspace --message-format=json --all-targets
146146
```
147147
.
148148
--
149-
[[rust-analyzer.checkOnSave.target]]rust-analyzer.checkOnSave.target (default: `null`)::
149+
[[rust-analyzer.checkOnSave.target]]rust-analyzer.checkOnSave.target (default: `[]`)::
150150
+
151151
--
152-
Check for a specific target. Defaults to
152+
Check for specific targets. Defaults to
153153
`#rust-analyzer.cargo.target#`.
154154
--
155155
[[rust-analyzer.completion.autoimport.enable]]rust-analyzer.completion.autoimport.enable (default: `true`)::

editors/code/package.json

+6-6
Original file line numberDiff line numberDiff line change
@@ -566,12 +566,12 @@
566566
}
567567
},
568568
"rust-analyzer.checkOnSave.target": {
569-
"markdownDescription": "Check for a specific target. Defaults to\n`#rust-analyzer.cargo.target#`.",
570-
"default": null,
571-
"type": [
572-
"null",
573-
"string"
574-
]
569+
"markdownDescription": "Check for specific targets. Defaults to\n`#rust-analyzer.cargo.target#`.",
570+
"default": [],
571+
"type": "array",
572+
"items": {
573+
"type": "string"
574+
}
575575
},
576576
"rust-analyzer.completion.autoimport.enable": {
577577
"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)