mirror of
https://github.com/rust-lang/cargo.git
synced 2025-10-01 11:30:39 +00:00
Get all members as available targets
even though default-members was specified. (#15199)
### What does this PR try to resolve? The old behavior gets members from `default-members` if specified in a virtual workspace, this PR gets all workspace members for `Available` target hints. Fixes https://github.com/rust-lang/cargo/issues/14544 ### How should we test and review this PR? The first commit added the test, the second commit addressed the issue. ### Additional information
This commit is contained in:
commit
726e2a70ea
@ -374,6 +374,7 @@ pub fn create_bcx<'a, 'gctx>(
|
|||||||
let generator = UnitGenerator {
|
let generator = UnitGenerator {
|
||||||
ws,
|
ws,
|
||||||
packages: &to_builds,
|
packages: &to_builds,
|
||||||
|
spec,
|
||||||
target_data: &target_data,
|
target_data: &target_data,
|
||||||
filter,
|
filter,
|
||||||
requested_kinds: &build_config.requested_kinds,
|
requested_kinds: &build_config.requested_kinds,
|
||||||
|
@ -17,6 +17,7 @@ use crate::util::{closest_msg, CargoResult};
|
|||||||
|
|
||||||
use super::compile_filter::{CompileFilter, FilterRule, LibRule};
|
use super::compile_filter::{CompileFilter, FilterRule, LibRule};
|
||||||
use super::packages::build_glob;
|
use super::packages::build_glob;
|
||||||
|
use super::Packages;
|
||||||
|
|
||||||
/// A proposed target.
|
/// A proposed target.
|
||||||
///
|
///
|
||||||
@ -47,6 +48,7 @@ struct Proposal<'a> {
|
|||||||
pub(super) struct UnitGenerator<'a, 'gctx> {
|
pub(super) struct UnitGenerator<'a, 'gctx> {
|
||||||
pub ws: &'a Workspace<'gctx>,
|
pub ws: &'a Workspace<'gctx>,
|
||||||
pub packages: &'a [&'a Package],
|
pub packages: &'a [&'a Package],
|
||||||
|
pub spec: &'a Packages,
|
||||||
pub target_data: &'a RustcTargetData<'gctx>,
|
pub target_data: &'a RustcTargetData<'gctx>,
|
||||||
pub filter: &'a CompileFilter,
|
pub filter: &'a CompileFilter,
|
||||||
pub requested_kinds: &'a [CompileKind],
|
pub requested_kinds: &'a [CompileKind],
|
||||||
@ -247,15 +249,15 @@ impl<'a> UnitGenerator<'a, '_> {
|
|||||||
mode: CompileMode,
|
mode: CompileMode,
|
||||||
) -> CargoResult<Vec<Proposal<'a>>> {
|
) -> CargoResult<Vec<Proposal<'a>>> {
|
||||||
let is_glob = is_glob_pattern(target_name);
|
let is_glob = is_glob_pattern(target_name);
|
||||||
let proposals = if is_glob {
|
let pattern = build_glob(target_name)?;
|
||||||
let pattern = build_glob(target_name)?;
|
let filter = |t: &Target| {
|
||||||
let filter = |t: &Target| is_expected_kind(t) && pattern.matches(t.name());
|
if is_glob {
|
||||||
self.filter_targets(filter, true, mode)
|
is_expected_kind(t) && pattern.matches(t.name())
|
||||||
} else {
|
} else {
|
||||||
let filter = |t: &Target| t.name() == target_name && is_expected_kind(t);
|
is_expected_kind(t) && t.name() == target_name
|
||||||
self.filter_targets(filter, true, mode)
|
}
|
||||||
};
|
};
|
||||||
|
let proposals = self.filter_targets(filter, true, mode);
|
||||||
if proposals.is_empty() {
|
if proposals.is_empty() {
|
||||||
let targets = self
|
let targets = self
|
||||||
.packages
|
.packages
|
||||||
@ -267,35 +269,103 @@ impl<'a> UnitGenerator<'a, '_> {
|
|||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let suggestion = closest_msg(target_name, targets.iter(), |t| t.name(), "target");
|
let suggestion = closest_msg(target_name, targets.iter(), |t| t.name(), "target");
|
||||||
|
let targets_elsewhere = self.get_targets_from_other_packages(filter)?;
|
||||||
|
let need_append_targets_elsewhere = !targets_elsewhere.is_empty();
|
||||||
|
let append_targets_elsewhere = |msg: &mut String, prefix: &str| {
|
||||||
|
let mut available_msg = Vec::new();
|
||||||
|
for (package, targets) in targets_elsewhere {
|
||||||
|
if !targets.is_empty() {
|
||||||
|
available_msg.push(format!(
|
||||||
|
"help: Available {target_desc} in `{package}` package:"
|
||||||
|
));
|
||||||
|
for target in targets {
|
||||||
|
available_msg.push(format!(" {target}"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !available_msg.is_empty() {
|
||||||
|
write!(msg, "{prefix}{}", available_msg.join("\n"))?;
|
||||||
|
}
|
||||||
|
CargoResult::Ok(())
|
||||||
|
};
|
||||||
|
|
||||||
|
let unmatched_packages = || match self.spec {
|
||||||
|
Packages::Default | Packages::OptOut(_) | Packages::All(_) => {
|
||||||
|
"default-run packages".to_owned()
|
||||||
|
}
|
||||||
|
Packages::Packages(packages) => {
|
||||||
|
let first = packages
|
||||||
|
.first()
|
||||||
|
.expect("The number of packages must be at least 1");
|
||||||
|
if packages.len() == 1 {
|
||||||
|
format!("`{}` package", first)
|
||||||
|
} else {
|
||||||
|
format!("`{}`, ... packages", first)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut msg = String::new();
|
||||||
if !suggestion.is_empty() {
|
if !suggestion.is_empty() {
|
||||||
anyhow::bail!(
|
write!(
|
||||||
"no {} target {} `{}`{}",
|
msg,
|
||||||
|
"no {} target {} `{}` in {}{}",
|
||||||
target_desc,
|
target_desc,
|
||||||
if is_glob { "matches pattern" } else { "named" },
|
if is_glob { "matches pattern" } else { "named" },
|
||||||
target_name,
|
target_name,
|
||||||
suggestion
|
unmatched_packages(),
|
||||||
);
|
suggestion,
|
||||||
|
)?;
|
||||||
|
append_targets_elsewhere(&mut msg, "\n")?;
|
||||||
} else {
|
} else {
|
||||||
let mut msg = String::new();
|
|
||||||
writeln!(
|
writeln!(
|
||||||
msg,
|
msg,
|
||||||
"no {} target {} `{}`.",
|
"no {} target {} `{}` in {}.",
|
||||||
target_desc,
|
target_desc,
|
||||||
if is_glob { "matches pattern" } else { "named" },
|
if is_glob { "matches pattern" } else { "named" },
|
||||||
target_name,
|
target_name,
|
||||||
|
unmatched_packages()
|
||||||
)?;
|
)?;
|
||||||
if !targets.is_empty() {
|
|
||||||
|
append_targets_elsewhere(&mut msg, "")?;
|
||||||
|
if !targets.is_empty() && !need_append_targets_elsewhere {
|
||||||
writeln!(msg, "Available {} targets:", target_desc)?;
|
writeln!(msg, "Available {} targets:", target_desc)?;
|
||||||
for target in targets {
|
for target in targets {
|
||||||
writeln!(msg, " {}", target.name())?;
|
writeln!(msg, " {}", target.name())?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
anyhow::bail!(msg);
|
|
||||||
}
|
}
|
||||||
|
anyhow::bail!(msg);
|
||||||
}
|
}
|
||||||
Ok(proposals)
|
Ok(proposals)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_targets_from_other_packages(
|
||||||
|
&self,
|
||||||
|
filter_fn: impl Fn(&Target) -> bool,
|
||||||
|
) -> CargoResult<Vec<(&str, Vec<&str>)>> {
|
||||||
|
let packages = Packages::All(Vec::new()).get_packages(self.ws)?;
|
||||||
|
let targets = packages
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|pkg| {
|
||||||
|
let mut targets: Vec<_> = pkg
|
||||||
|
.manifest()
|
||||||
|
.targets()
|
||||||
|
.iter()
|
||||||
|
.filter_map(|target| filter_fn(target).then(|| target.name()))
|
||||||
|
.collect();
|
||||||
|
if targets.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
targets.sort();
|
||||||
|
Some((pkg.name().as_str(), targets))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Ok(targets)
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns a list of proposed targets based on command-line target selection flags.
|
/// Returns a list of proposed targets based on command-line target selection flags.
|
||||||
fn list_rule_targets(
|
fn list_rule_targets(
|
||||||
&self,
|
&self,
|
||||||
|
@ -1337,7 +1337,7 @@ fn cargo_compile_with_filename() {
|
|||||||
p.cargo("build --bin bin.rs")
|
p.cargo("build --bin bin.rs")
|
||||||
.with_status(101)
|
.with_status(101)
|
||||||
.with_stderr_data(str![[r#"
|
.with_stderr_data(str![[r#"
|
||||||
[ERROR] no bin target named `bin.rs`.
|
[ERROR] no bin target named `bin.rs` in default-run packages.
|
||||||
Available bin targets:
|
Available bin targets:
|
||||||
a
|
a
|
||||||
|
|
||||||
@ -1348,7 +1348,7 @@ Available bin targets:
|
|||||||
p.cargo("build --bin a.rs")
|
p.cargo("build --bin a.rs")
|
||||||
.with_status(101)
|
.with_status(101)
|
||||||
.with_stderr_data(str![[r#"
|
.with_stderr_data(str![[r#"
|
||||||
[ERROR] no bin target named `a.rs`
|
[ERROR] no bin target named `a.rs` in default-run packages
|
||||||
|
|
||||||
[HELP] a target with a similar name exists: `a`
|
[HELP] a target with a similar name exists: `a`
|
||||||
|
|
||||||
@ -1358,7 +1358,7 @@ Available bin targets:
|
|||||||
p.cargo("build --example example.rs")
|
p.cargo("build --example example.rs")
|
||||||
.with_status(101)
|
.with_status(101)
|
||||||
.with_stderr_data(str![[r#"
|
.with_stderr_data(str![[r#"
|
||||||
[ERROR] no example target named `example.rs`.
|
[ERROR] no example target named `example.rs` in default-run packages.
|
||||||
Available example targets:
|
Available example targets:
|
||||||
a
|
a
|
||||||
|
|
||||||
@ -1369,7 +1369,7 @@ Available example targets:
|
|||||||
p.cargo("build --example a.rs")
|
p.cargo("build --example a.rs")
|
||||||
.with_status(101)
|
.with_status(101)
|
||||||
.with_stderr_data(str![[r#"
|
.with_stderr_data(str![[r#"
|
||||||
[ERROR] no example target named `a.rs`
|
[ERROR] no example target named `a.rs` in default-run packages
|
||||||
|
|
||||||
[HELP] a target with a similar name exists: `a`
|
[HELP] a target with a similar name exists: `a`
|
||||||
|
|
||||||
@ -5906,7 +5906,7 @@ fn target_filters_workspace() {
|
|||||||
ws.cargo("build -v --example ex")
|
ws.cargo("build -v --example ex")
|
||||||
.with_status(101)
|
.with_status(101)
|
||||||
.with_stderr_data(str![[r#"
|
.with_stderr_data(str![[r#"
|
||||||
[ERROR] no example target named `ex`
|
[ERROR] no example target named `ex` in default-run packages
|
||||||
|
|
||||||
[HELP] a target with a similar name exists: `ex1`
|
[HELP] a target with a similar name exists: `ex1`
|
||||||
|
|
||||||
@ -5916,7 +5916,7 @@ fn target_filters_workspace() {
|
|||||||
ws.cargo("build -v --example 'ex??'")
|
ws.cargo("build -v --example 'ex??'")
|
||||||
.with_status(101)
|
.with_status(101)
|
||||||
.with_stderr_data(str![[r#"
|
.with_stderr_data(str![[r#"
|
||||||
[ERROR] no example target matches pattern `ex??`
|
[ERROR] no example target matches pattern `ex??` in default-run packages
|
||||||
|
|
||||||
[HELP] a target with a similar name exists: `ex1`
|
[HELP] a target with a similar name exists: `ex1`
|
||||||
|
|
||||||
|
@ -623,7 +623,7 @@ automatically infer them to be a target, such as in subfolders.
|
|||||||
|
|
||||||
For more information on this warning you can consult
|
For more information on this warning you can consult
|
||||||
https://github.com/rust-lang/cargo/issues/5330
|
https://github.com/rust-lang/cargo/issues/5330
|
||||||
[ERROR] no example target named `a`.
|
[ERROR] no example target named `a` in default-run packages.
|
||||||
Available example targets:
|
Available example targets:
|
||||||
do_magic
|
do_magic
|
||||||
|
|
||||||
@ -655,7 +655,7 @@ fn run_example_autodiscover_2015_with_autoexamples_disabled() {
|
|||||||
p.cargo("run --example a")
|
p.cargo("run --example a")
|
||||||
.with_status(101)
|
.with_status(101)
|
||||||
.with_stderr_data(str![[r#"
|
.with_stderr_data(str![[r#"
|
||||||
[ERROR] no example target named `a`.
|
[ERROR] no example target named `a` in default-run packages.
|
||||||
Available example targets:
|
Available example targets:
|
||||||
do_magic
|
do_magic
|
||||||
|
|
||||||
@ -743,7 +743,7 @@ fn run_with_filename() {
|
|||||||
p.cargo("run --bin bin.rs")
|
p.cargo("run --bin bin.rs")
|
||||||
.with_status(101)
|
.with_status(101)
|
||||||
.with_stderr_data(str![[r#"
|
.with_stderr_data(str![[r#"
|
||||||
[ERROR] no bin target named `bin.rs`.
|
[ERROR] no bin target named `bin.rs` in default-run packages.
|
||||||
Available bin targets:
|
Available bin targets:
|
||||||
a
|
a
|
||||||
|
|
||||||
@ -754,7 +754,7 @@ Available bin targets:
|
|||||||
p.cargo("run --bin a.rs")
|
p.cargo("run --bin a.rs")
|
||||||
.with_status(101)
|
.with_status(101)
|
||||||
.with_stderr_data(str![[r#"
|
.with_stderr_data(str![[r#"
|
||||||
[ERROR] no bin target named `a.rs`
|
[ERROR] no bin target named `a.rs` in default-run packages
|
||||||
|
|
||||||
[HELP] a target with a similar name exists: `a`
|
[HELP] a target with a similar name exists: `a`
|
||||||
|
|
||||||
@ -764,7 +764,7 @@ Available bin targets:
|
|||||||
p.cargo("run --example example.rs")
|
p.cargo("run --example example.rs")
|
||||||
.with_status(101)
|
.with_status(101)
|
||||||
.with_stderr_data(str![[r#"
|
.with_stderr_data(str![[r#"
|
||||||
[ERROR] no example target named `example.rs`.
|
[ERROR] no example target named `example.rs` in default-run packages.
|
||||||
Available example targets:
|
Available example targets:
|
||||||
a
|
a
|
||||||
|
|
||||||
@ -775,7 +775,7 @@ Available example targets:
|
|||||||
p.cargo("run --example a.rs")
|
p.cargo("run --example a.rs")
|
||||||
.with_status(101)
|
.with_status(101)
|
||||||
.with_stderr_data(str![[r#"
|
.with_stderr_data(str![[r#"
|
||||||
[ERROR] no example target named `a.rs`
|
[ERROR] no example target named `a.rs` in default-run packages
|
||||||
|
|
||||||
[HELP] a target with a similar name exists: `a`
|
[HELP] a target with a similar name exists: `a`
|
||||||
|
|
||||||
|
@ -2447,7 +2447,7 @@ fn bad_example() {
|
|||||||
p.cargo("run --example foo")
|
p.cargo("run --example foo")
|
||||||
.with_status(101)
|
.with_status(101)
|
||||||
.with_stderr_data(str![[r#"
|
.with_stderr_data(str![[r#"
|
||||||
[ERROR] no example target named `foo`.
|
[ERROR] no example target named `foo` in default-run packages.
|
||||||
|
|
||||||
|
|
||||||
"#]])
|
"#]])
|
||||||
@ -2455,7 +2455,7 @@ fn bad_example() {
|
|||||||
p.cargo("run --bin foo")
|
p.cargo("run --bin foo")
|
||||||
.with_status(101)
|
.with_status(101)
|
||||||
.with_stderr_data(str![[r#"
|
.with_stderr_data(str![[r#"
|
||||||
[ERROR] no bin target named `foo`.
|
[ERROR] no bin target named `foo` in default-run packages.
|
||||||
|
|
||||||
|
|
||||||
"#]])
|
"#]])
|
||||||
|
@ -2716,3 +2716,152 @@ fn nonexistence_package_together_with_workspace() {
|
|||||||
"#]])
|
"#]])
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See rust-lang/cargo#14544
|
||||||
|
#[cargo_test]
|
||||||
|
fn print_available_targets_within_virtual_workspace() {
|
||||||
|
let p = project()
|
||||||
|
.file(
|
||||||
|
"Cargo.toml",
|
||||||
|
r#"
|
||||||
|
[workspace]
|
||||||
|
resolver = "3"
|
||||||
|
members = ["crate1", "crate2", "pattern1", "pattern2"]
|
||||||
|
|
||||||
|
default-members = ["crate1"]
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.file("crate1/src/main.rs", "fn main(){}")
|
||||||
|
.file(
|
||||||
|
"crate1/Cargo.toml",
|
||||||
|
r#"
|
||||||
|
[package]
|
||||||
|
name = "crate1"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.file("crate2/src/main.rs", "fn main(){}")
|
||||||
|
.file(
|
||||||
|
"crate2/Cargo.toml",
|
||||||
|
r#"
|
||||||
|
[package]
|
||||||
|
name = "crate2"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.file("pattern1/src/main.rs", "fn main(){}")
|
||||||
|
.file(
|
||||||
|
"pattern1/Cargo.toml",
|
||||||
|
r#"
|
||||||
|
[package]
|
||||||
|
name = "pattern1"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.file("pattern2/src/main.rs", "fn main(){}")
|
||||||
|
.file(
|
||||||
|
"pattern2/Cargo.toml",
|
||||||
|
r#"
|
||||||
|
[package]
|
||||||
|
name = "pattern2"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.file("another/src/main.rs", "fn main(){}")
|
||||||
|
.file(
|
||||||
|
"another/Cargo.toml",
|
||||||
|
r#"
|
||||||
|
[package]
|
||||||
|
name = "another"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
|
||||||
|
let p = p.build();
|
||||||
|
p.cargo("run --bin")
|
||||||
|
.with_status(101)
|
||||||
|
.with_stderr_data(str![[r#"
|
||||||
|
[ERROR] "--bin" takes one argument.
|
||||||
|
Available binaries:
|
||||||
|
crate1
|
||||||
|
|
||||||
|
|
||||||
|
"#]])
|
||||||
|
.run();
|
||||||
|
|
||||||
|
p.cargo("run -p crate1 --bin crate2")
|
||||||
|
.with_status(101)
|
||||||
|
.with_stderr_data(str![[r#"
|
||||||
|
[ERROR] no bin target named `crate2` in `crate1` package
|
||||||
|
|
||||||
|
[HELP] a target with a similar name exists: `crate1`
|
||||||
|
[HELP] Available bin in `crate2` package:
|
||||||
|
crate2
|
||||||
|
|
||||||
|
"#]])
|
||||||
|
.run();
|
||||||
|
|
||||||
|
p.cargo("check -p crate1 -p pattern1 -p pattern2 --bin crate2")
|
||||||
|
.with_status(101)
|
||||||
|
.with_stderr_data(str![[r#"
|
||||||
|
[ERROR] no bin target named `crate2` in `crate1`, ... packages
|
||||||
|
|
||||||
|
[HELP] a target with a similar name exists: `crate1`
|
||||||
|
[HELP] Available bin in `crate2` package:
|
||||||
|
crate2
|
||||||
|
|
||||||
|
"#]])
|
||||||
|
.run();
|
||||||
|
|
||||||
|
p.cargo("run --bin crate2")
|
||||||
|
.with_status(101)
|
||||||
|
.with_stderr_data(str![[r#"
|
||||||
|
[ERROR] no bin target named `crate2` in default-run packages
|
||||||
|
|
||||||
|
[HELP] a target with a similar name exists: `crate1`
|
||||||
|
[HELP] Available bin in `crate2` package:
|
||||||
|
crate2
|
||||||
|
|
||||||
|
"#]])
|
||||||
|
.run();
|
||||||
|
|
||||||
|
p.cargo("check --bin pattern*")
|
||||||
|
.with_status(101)
|
||||||
|
.with_stderr_data(str![[r#"
|
||||||
|
[ERROR] no bin target matches pattern `pattern*` in default-run packages.
|
||||||
|
[HELP] Available bin in `pattern1` package:
|
||||||
|
pattern1
|
||||||
|
[HELP] Available bin in `pattern2` package:
|
||||||
|
pattern2
|
||||||
|
|
||||||
|
"#]])
|
||||||
|
.run();
|
||||||
|
|
||||||
|
// This another branch that none of similar name exists, and print available targets in the
|
||||||
|
// default-members.
|
||||||
|
p.change_file(
|
||||||
|
"Cargo.toml",
|
||||||
|
r#"
|
||||||
|
[workspace]
|
||||||
|
resolver = "3"
|
||||||
|
members = ["crate1", "crate2", "another"]
|
||||||
|
|
||||||
|
default-members = ["another"]
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
|
||||||
|
p.cargo("run --bin crate2")
|
||||||
|
.with_status(101)
|
||||||
|
.with_stderr_data(str![[r#"
|
||||||
|
[ERROR] no bin target named `crate2` in default-run packages.
|
||||||
|
[HELP] Available bin in `crate2` package:
|
||||||
|
crate2
|
||||||
|
|
||||||
|
"#]])
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user