feat: Support passing multiple targets to cargo (for Rust 1.64.0+)
This commit is contained in:
parent
c6c932d3f3
commit
0d4737adb6
@ -40,7 +40,7 @@ pub enum InvocationLocation {
|
|||||||
pub enum FlycheckConfig {
|
pub enum FlycheckConfig {
|
||||||
CargoCommand {
|
CargoCommand {
|
||||||
command: String,
|
command: String,
|
||||||
target_triple: Option<String>,
|
target_triples: Vec<String>,
|
||||||
all_targets: bool,
|
all_targets: bool,
|
||||||
no_default_features: bool,
|
no_default_features: bool,
|
||||||
all_features: bool,
|
all_features: bool,
|
||||||
@ -286,7 +286,7 @@ fn check_command(&self) -> Command {
|
|||||||
let (mut cmd, args) = match &self.config {
|
let (mut cmd, args) = match &self.config {
|
||||||
FlycheckConfig::CargoCommand {
|
FlycheckConfig::CargoCommand {
|
||||||
command,
|
command,
|
||||||
target_triple,
|
target_triples,
|
||||||
no_default_features,
|
no_default_features,
|
||||||
all_targets,
|
all_targets,
|
||||||
all_features,
|
all_features,
|
||||||
@ -300,7 +300,7 @@ fn check_command(&self) -> Command {
|
|||||||
cmd.args(&["--workspace", "--message-format=json", "--manifest-path"])
|
cmd.args(&["--workspace", "--message-format=json", "--manifest-path"])
|
||||||
.arg(self.root.join("Cargo.toml").as_os_str());
|
.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()]);
|
cmd.args(&["--target", target.as_str()]);
|
||||||
}
|
}
|
||||||
if *all_targets {
|
if *all_targets {
|
||||||
|
@ -69,7 +69,7 @@ fn build_command(config: &CargoConfig) -> io::Result<Command> {
|
|||||||
cmd.args(&["check", "--quiet", "--workspace", "--message-format=json"]);
|
cmd.args(&["check", "--quiet", "--workspace", "--message-format=json"]);
|
||||||
|
|
||||||
// --all-targets includes tests, benches and examples in addition to the
|
// --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.
|
// flag below.
|
||||||
cmd.arg("--all-targets");
|
cmd.arg("--all-targets");
|
||||||
|
|
||||||
|
@ -270,11 +270,7 @@ pub fn fetch_metadata(
|
|||||||
config: &CargoConfig,
|
config: &CargoConfig,
|
||||||
progress: &dyn Fn(String),
|
progress: &dyn Fn(String),
|
||||||
) -> Result<cargo_metadata::Metadata> {
|
) -> Result<cargo_metadata::Metadata> {
|
||||||
let target = config
|
let targets = find_list_of_build_targets(config, cargo_toml);
|
||||||
.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 mut meta = MetadataCommand::new();
|
let mut meta = MetadataCommand::new();
|
||||||
meta.cargo_path(toolchain::cargo());
|
meta.cargo_path(toolchain::cargo());
|
||||||
@ -294,8 +290,12 @@ pub fn fetch_metadata(
|
|||||||
}
|
}
|
||||||
meta.current_dir(current_dir.as_os_str());
|
meta.current_dir(current_dir.as_os_str());
|
||||||
|
|
||||||
if let Some(target) = target {
|
if !targets.is_empty() {
|
||||||
meta.other_options(vec![String::from("--filter-platform"), target]);
|
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
|
// FIXME: Fetching metadata is a slow process, as it might require
|
||||||
@ -469,6 +469,19 @@ fn is_unique(&self, name: &str) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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(
|
fn rustc_discover_host_triple(
|
||||||
cargo_toml: &ManifestPath,
|
cargo_toml: &ManifestPath,
|
||||||
extra_env: &FxHashMap<String, String>,
|
extra_env: &FxHashMap<String, String>,
|
||||||
@ -499,7 +512,7 @@ fn rustc_discover_host_triple(
|
|||||||
fn cargo_config_build_target(
|
fn cargo_config_build_target(
|
||||||
cargo_toml: &ManifestPath,
|
cargo_toml: &ManifestPath,
|
||||||
extra_env: &FxHashMap<String, String>,
|
extra_env: &FxHashMap<String, String>,
|
||||||
) -> Option<String> {
|
) -> Vec<String> {
|
||||||
let mut cargo_config = Command::new(toolchain::cargo());
|
let mut cargo_config = Command::new(toolchain::cargo());
|
||||||
cargo_config.envs(extra_env);
|
cargo_config.envs(extra_env);
|
||||||
cargo_config
|
cargo_config
|
||||||
@ -507,12 +520,21 @@ fn cargo_config_build_target(
|
|||||||
.args(&["-Z", "unstable-options", "config", "get", "build.target"])
|
.args(&["-Z", "unstable-options", "config", "get", "build.target"])
|
||||||
.env("RUSTC_BOOTSTRAP", "1");
|
.env("RUSTC_BOOTSTRAP", "1");
|
||||||
// if successful we receive `build.target = "target-triple"`
|
// if successful we receive `build.target = "target-triple"`
|
||||||
|
// or `build.target = ["<target 1>", ..]`
|
||||||
tracing::debug!("Discovering cargo config target by {:?}", cargo_config);
|
tracing::debug!("Discovering cargo config target by {:?}", cargo_config);
|
||||||
match utf8_stdout(cargo_config) {
|
utf8_stdout(cargo_config).map(parse_output_cargo_config_build_target).unwrap_or_default()
|
||||||
Ok(stdout) => stdout
|
}
|
||||||
.strip_prefix("build.target = \"")
|
|
||||||
.and_then(|stdout| stdout.strip_suffix('"'))
|
fn parse_output_cargo_config_build_target(stdout: String) -> Vec<String> {
|
||||||
.map(ToOwned::to_owned),
|
let trimmed = stdout.trim_start_matches("build.target = ").trim_matches('"');
|
||||||
Err(_) => None,
|
|
||||||
}
|
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()
|
||||||
}
|
}
|
||||||
|
@ -118,6 +118,8 @@ struct ConfigData {
|
|||||||
/// This option does not take effect until rust-analyzer is restarted.
|
/// This option does not take effect until rust-analyzer is restarted.
|
||||||
cargo_sysroot: Option<String> = "\"discover\"",
|
cargo_sysroot: Option<String> = "\"discover\"",
|
||||||
/// Compilation target override (target triple).
|
/// 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",
|
cargo_target: Option<String> = "null",
|
||||||
/// Unsets `#[cfg(test)]` for the specified crates.
|
/// Unsets `#[cfg(test)]` for the specified crates.
|
||||||
cargo_unsetTest: Vec<String> = "[\"core\"]",
|
cargo_unsetTest: Vec<String> = "[\"core\"]",
|
||||||
@ -174,9 +176,13 @@ struct ConfigData {
|
|||||||
/// ```
|
/// ```
|
||||||
/// .
|
/// .
|
||||||
checkOnSave_overrideCommand: Option<Vec<String>> = "null",
|
checkOnSave_overrideCommand: Option<Vec<String>> = "null",
|
||||||
/// Check for a specific target. Defaults to
|
/// Check for specific targets. Defaults to `#rust-analyzer.cargo.target#` if empty.
|
||||||
/// `#rust-analyzer.cargo.target#`.
|
///
|
||||||
checkOnSave_target: Option<String> = "null",
|
/// 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.
|
/// 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.
|
/// Note that your client must specify the `additionalTextEdits` LSP client capability to truly have this feature enabled.
|
||||||
@ -1147,11 +1153,10 @@ pub fn flycheck(&self) -> Option<FlycheckConfig> {
|
|||||||
}
|
}
|
||||||
Some(_) | None => FlycheckConfig::CargoCommand {
|
Some(_) | None => FlycheckConfig::CargoCommand {
|
||||||
command: self.data.checkOnSave_command.clone(),
|
command: self.data.checkOnSave_command.clone(),
|
||||||
target_triple: self
|
target_triples: match &self.data.checkOnSave_target.0[..] {
|
||||||
.data
|
[] => self.data.cargo_target.clone().into_iter().collect(),
|
||||||
.checkOnSave_target
|
targets => targets.into(),
|
||||||
.clone()
|
},
|
||||||
.or_else(|| self.data.cargo_target.clone()),
|
|
||||||
all_targets: self.data.checkOnSave_allTargets,
|
all_targets: self.data.checkOnSave_allTargets,
|
||||||
no_default_features: self
|
no_default_features: self
|
||||||
.data
|
.data
|
||||||
@ -1657,6 +1662,9 @@ enum InvocationStrategy {
|
|||||||
PerWorkspace,
|
PerWorkspace,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
|
struct CheckOnSaveTargets(#[serde(deserialize_with = "single_or_array")] Vec<String>);
|
||||||
|
|
||||||
#[derive(Deserialize, Debug, Clone)]
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
enum InvocationLocation {
|
enum InvocationLocation {
|
||||||
@ -2118,6 +2126,17 @@ macro_rules! set {
|
|||||||
"The command will be executed in the project root."
|
"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),
|
_ => panic!("missing entry for {}: {}", ty, default),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
Check for specific targets. Defaults to `#rust-analyzer.cargo.target#` if empty.
|
||||||
`#rust-analyzer.cargo.target#`.
|
|
||||||
|
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`)::
|
[[rust-analyzer.completion.autoimport.enable]]rust-analyzer.completion.autoimport.enable (default: `true`)::
|
||||||
+
|
+
|
||||||
|
@ -634,11 +634,18 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rust-analyzer.checkOnSave.target": {
|
"rust-analyzer.checkOnSave.target": {
|
||||||
"markdownDescription": "Check for a specific target. Defaults to\n`#rust-analyzer.cargo.target#`.",
|
"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": null,
|
"default": [],
|
||||||
"type": [
|
"anyOf": [
|
||||||
"null",
|
{
|
||||||
"string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"rust-analyzer.completion.autoimport.enable": {
|
"rust-analyzer.completion.autoimport.enable": {
|
||||||
|
Loading…
Reference in New Issue
Block a user