Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/flycheck/src/lib.rs6
-rw-r--r--crates/project-model/src/build_scripts.rs2
-rw-r--r--crates/project-model/src/cargo_workspace.rs50
-rw-r--r--crates/rust-analyzer/src/config.rs35
-rw-r--r--docs/user/generated_config.adoc10
-rw-r--r--editors/code/package.json17
6 files changed, 86 insertions, 34 deletions
diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs
index ff507a52d5..8f93dad06e 100644
--- a/crates/flycheck/src/lib.rs
+++ b/crates/flycheck/src/lib.rs
@@ -40,7 +40,7 @@ pub enum InvocationLocation {
pub enum FlycheckConfig {
CargoCommand {
command: String,
- target_triple: Option<String>,
+ target_triples: Vec<String>,
all_targets: bool,
no_default_features: bool,
all_features: bool,
@@ -286,7 +286,7 @@ impl FlycheckActor {
let (mut cmd, args) = match &self.config {
FlycheckConfig::CargoCommand {
command,
- target_triple,
+ target_triples,
no_default_features,
all_targets,
all_features,
@@ -300,7 +300,7 @@ impl FlycheckActor {
cmd.args(&["--workspace", "--message-format=json", "--manifest-path"])
.arg(self.root.join("Cargo.toml").as_os_str());
- if let Some(target) = target_triple {
+ for target in target_triples {
cmd.args(&["--target", target.as_str()]);
}
if *all_targets {
diff --git a/crates/project-model/src/build_scripts.rs b/crates/project-model/src/build_scripts.rs
index a26a7c57ac..ae2b41f27d 100644
--- a/crates/project-model/src/build_scripts.rs
+++ b/crates/project-model/src/build_scripts.rs
@@ -69,7 +69,7 @@ impl WorkspaceBuildScripts {
cmd.args(&["check", "--quiet", "--workspace", "--message-format=json"]);
// --all-targets includes tests, benches and examples in addition to the
- // default lib and bins. This is an independent concept from the --targets
+ // default lib and bins. This is an independent concept from the --target
// flag below.
cmd.arg("--all-targets");
diff --git a/crates/project-model/src/cargo_workspace.rs b/crates/project-model/src/cargo_workspace.rs
index b4c2ba4367..02ec7a4f6f 100644
--- a/crates/project-model/src/cargo_workspace.rs
+++ b/crates/project-model/src/cargo_workspace.rs
@@ -270,11 +270,7 @@ impl CargoWorkspace {
config: &CargoConfig,
progress: &dyn Fn(String),
) -> Result<cargo_metadata::Metadata> {
- let target = config
- .target
- .clone()
- .or_else(|| cargo_config_build_target(cargo_toml, &config.extra_env))
- .or_else(|| rustc_discover_host_triple(cargo_toml, &config.extra_env));
+ let targets = find_list_of_build_targets(config, cargo_toml);
let mut meta = MetadataCommand::new();
meta.cargo_path(toolchain::cargo());
@@ -294,8 +290,12 @@ impl CargoWorkspace {
}
meta.current_dir(current_dir.as_os_str());
- if let Some(target) = target {
- meta.other_options(vec![String::from("--filter-platform"), target]);
+ if !targets.is_empty() {
+ let other_options: Vec<_> = targets
+ .into_iter()
+ .flat_map(|target| ["--filter-platform".to_string(), target])
+ .collect();
+ meta.other_options(other_options);
}
// FIXME: Fetching metadata is a slow process, as it might require
@@ -469,6 +469,19 @@ impl CargoWorkspace {
}
}
+fn find_list_of_build_targets(config: &CargoConfig, cargo_toml: &ManifestPath) -> Vec<String> {
+ if let Some(target) = &config.target {
+ return [target.into()].to_vec();
+ }
+
+ let build_targets = cargo_config_build_target(cargo_toml, &config.extra_env);
+ if !build_targets.is_empty() {
+ return build_targets;
+ }
+
+ rustc_discover_host_triple(cargo_toml, &config.extra_env).into_iter().collect()
+}
+
fn rustc_discover_host_triple(
cargo_toml: &ManifestPath,
extra_env: &FxHashMap<String, String>,
@@ -499,7 +512,7 @@ fn rustc_discover_host_triple(
fn cargo_config_build_target(
cargo_toml: &ManifestPath,
extra_env: &FxHashMap<String, String>,
-) -> Option<String> {
+) -> Vec<String> {
let mut cargo_config = Command::new(toolchain::cargo());
cargo_config.envs(extra_env);
cargo_config
@@ -507,12 +520,21 @@ fn cargo_config_build_target(
.args(&["-Z", "unstable-options", "config", "get", "build.target"])
.env("RUSTC_BOOTSTRAP", "1");
// if successful we receive `build.target = "target-triple"`
+ // or `build.target = ["<target 1>", ..]`
tracing::debug!("Discovering cargo config target by {:?}", cargo_config);
- match utf8_stdout(cargo_config) {
- Ok(stdout) => stdout
- .strip_prefix("build.target = \"")
- .and_then(|stdout| stdout.strip_suffix('"'))
- .map(ToOwned::to_owned),
- Err(_) => None,
+ utf8_stdout(cargo_config).map(parse_output_cargo_config_build_target).unwrap_or_default()
+}
+
+fn parse_output_cargo_config_build_target(stdout: String) -> Vec<String> {
+ let trimmed = stdout.trim_start_matches("build.target = ").trim_matches('"');
+
+ if !trimmed.starts_with('[') {
+ return [trimmed.to_string()].to_vec();
+ }
+
+ let res = serde_json::from_str(trimmed);
+ if let Err(e) = &res {
+ tracing::warn!("Failed to parse `build.target` as an array of target: {}`", e);
}
+ res.unwrap_or_default()
}
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 25e341391a..6b2f22faa7 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -118,6 +118,8 @@ config_data! {
/// This option does not take effect until rust-analyzer is restarted.
cargo_sysroot: Option<String> = "\"discover\"",
/// Compilation target override (target triple).
+ // FIXME(@poliorcetics): move to multiple targets here too, but this will need more work
+ // than `checkOnSave_target`
cargo_target: Option<String> = "null",
/// Unsets `#[cfg(test)]` for the specified crates.
cargo_unsetTest: Vec<String> = "[\"core\"]",
@@ -174,9 +176,13 @@ config_data! {
/// ```
/// .
checkOnSave_overrideCommand: Option<Vec<String>> = "null",
- /// Check for a specific target. Defaults to
- /// `#rust-analyzer.cargo.target#`.
- checkOnSave_target: Option<String> = "null",
+ /// Check for specific targets. Defaults to `#rust-analyzer.cargo.target#` if empty.
+ ///
+ /// Can be a single target, e.g. `"x86_64-unknown-linux-gnu"` or a list of targets, e.g.
+ /// `["aarch64-apple-darwin", "x86_64-apple-darwin"]`.
+ ///
+ /// Aliased as `"checkOnSave.targets"`.
+ checkOnSave_target | checkOnSave_targets: CheckOnSaveTargets = "[]",
/// Toggles the additional completions that automatically add imports when completed.
/// Note that your client must specify the `additionalTextEdits` LSP client capability to truly have this feature enabled.
@@ -1147,11 +1153,10 @@ impl Config {
}
Some(_) | None => FlycheckConfig::CargoCommand {
command: self.data.checkOnSave_command.clone(),
- target_triple: self
- .data
- .checkOnSave_target
- .clone()
- .or_else(|| self.data.cargo_target.clone()),
+ target_triples: match &self.data.checkOnSave_target.0[..] {
+ [] => self.data.cargo_target.clone().into_iter().collect(),
+ targets => targets.into(),
+ },
all_targets: self.data.checkOnSave_allTargets,
no_default_features: self
.data
@@ -1658,6 +1663,9 @@ enum InvocationStrategy {
}
#[derive(Deserialize, Debug, Clone)]
+struct CheckOnSaveTargets(#[serde(deserialize_with = "single_or_array")] Vec<String>);
+
+#[derive(Deserialize, Debug, Clone)]
#[serde(rename_all = "snake_case")]
enum InvocationLocation {
Root,
@@ -2118,6 +2126,17 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json
"The command will be executed in the project root."
],
},
+ "CheckOnSaveTargets" => set! {
+ "anyOf": [
+ {
+ "type": "string",
+ },
+ {
+ "type": "array",
+ "items": { "type": "string" }
+ },
+ ],
+ },
_ => panic!("missing entry for {}: {}", ty, default),
}
diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc
index da8e629807..57f950034c 100644
--- a/docs/user/generated_config.adoc
+++ b/docs/user/generated_config.adoc
@@ -190,11 +190,15 @@ cargo check --workspace --message-format=json --all-targets
```
.
--
-[[rust-analyzer.checkOnSave.target]]rust-analyzer.checkOnSave.target (default: `null`)::
+[[rust-analyzer.checkOnSave.target]]rust-analyzer.checkOnSave.target (default: `[]`)::
+
--
-Check for a specific target. Defaults to
-`#rust-analyzer.cargo.target#`.
+Check for specific targets. Defaults to `#rust-analyzer.cargo.target#` if empty.
+
+Can be a single target, e.g. `"x86_64-unknown-linux-gnu"` or a list of targets, e.g.
+`["aarch64-apple-darwin", "x86_64-apple-darwin"]`.
+
+Aliased as `"checkOnSave.targets"`.
--
[[rust-analyzer.completion.autoimport.enable]]rust-analyzer.completion.autoimport.enable (default: `true`)::
+
diff --git a/editors/code/package.json b/editors/code/package.json
index 0c78165960..762726842f 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -634,11 +634,18 @@
}
},
"rust-analyzer.checkOnSave.target": {
- "markdownDescription": "Check for a specific target. Defaults to\n`#rust-analyzer.cargo.target#`.",
- "default": null,
- "type": [
- "null",
- "string"
+ "markdownDescription": "Check for specific targets. Defaults to `#rust-analyzer.cargo.target#` if empty.\n\nCan be a single target, e.g. `\"x86_64-unknown-linux-gnu\"` or a list of targets, e.g.\n`[\"aarch64-apple-darwin\", \"x86_64-apple-darwin\"]`.\n\nAliased as `\"checkOnSave.targets\"`.",
+ "default": [],
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
]
},
"rust-analyzer.completion.autoimport.enable": {