mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 04:19:13 +00:00
Auto merge of #13290 - poliorcetics:multiple-targets, r=Veykril
Support multiple targets for checkOnSave (in conjunction with cargo 1.64.0+) This PR adds support for the ability to pass multiple `--target` flags when using `cargo` 1.64.0+. ## Questions I needed to change the type of two configurations options, but I did not plurialize the names to avoid too much churn, should I ? ## Zulip thread https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frust-analyzer/topic/Issue.2013282.20.28supporting.20multiple.20targets.20with.201.2E64.2B.29 ## Example To see it working, on a macOS machine: ```sh $ cd /tmp $ cargo new cargo-multiple-targets-support-ra-test $ cd !$ $ mkdir .cargo $ echo ' [build] target = [ "aarch64-apple-darwin", "x86_64-apple-darwin", ] ' > .cargo/config.toml $ echo ' fn main() { #[cfg(all(target_arch = "aarch64", target_os = "macos"))] { let a = std::fs::read_to_string("/tmp/test-read"); } #[cfg(all(target_arch = "x86_64", target_os = "macos"))] { let a = std::fs::read_to_string("/tmp/test-read"); } #[cfg(all(target_arch = "x86_64", target_os = "windows"))] { let a = std::fs::read_to_string("/tmp/test-read"); } } ' > src/main.rs # launch your favorite editor with the version of RA from this PR # # You should see warnings under the first two `let a = ...` but not the third ``` ## Screen  Helps with #13282
This commit is contained in:
commit
38fa47fd79
6 changed files with 88 additions and 36 deletions
|
@ -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");
|
||||
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue