Use batch warnings and only warn about used dependency packages

Signed-off-by: hi-rustin <rustin.liu@gmail.com>
This commit is contained in:
hi-rustin 2021-08-07 14:10:14 +08:00
parent cc891a0bc5
commit 27c103063c
3 changed files with 149 additions and 36 deletions

View file

@ -516,27 +516,14 @@ impl<'cfg> PackageSet<'cfg> {
if !used.insert(pkg_id) {
return Ok(());
}
let filtered_deps = resolve.deps(pkg_id).filter(|&(_id, deps)| {
deps.iter().any(|dep| {
if dep.kind() == DepKind::Development && has_dev_units == HasDevUnits::No {
return false;
}
// This is overly broad, since not all target-specific
// dependencies are used both for target and host. To tighten this
// up, this function would need to track "for_host" similar to how
// unit dependencies handles it.
if force_all_targets == ForceAllTargets::No {
let activated = requested_kinds
.iter()
.chain(Some(&CompileKind::Host))
.any(|kind| target_data.dep_platform_activated(dep, *kind));
if !activated {
return false;
}
}
true
})
});
let filtered_deps = PackageSet::filter_deps(
pkg_id,
resolve,
has_dev_units,
requested_kinds,
target_data,
force_all_targets,
);
for (dep_id, _deps) in filtered_deps {
collect_used_deps(
used,
@ -571,6 +558,66 @@ impl<'cfg> PackageSet<'cfg> {
Ok(())
}
/// Check if there are any dependency packages that do not have any libs.
pub(crate) fn no_lib_pkgs(
&self,
resolve: &Resolve,
root_ids: &[PackageId],
has_dev_units: HasDevUnits,
requested_kinds: &[CompileKind],
target_data: &RustcTargetData<'_>,
force_all_targets: ForceAllTargets,
) -> CargoResult<Vec<&Package>> {
let mut ret = vec![];
root_ids.iter().for_each(|pkg_id| {
PackageSet::filter_deps(
*pkg_id,
resolve,
has_dev_units,
requested_kinds,
target_data,
force_all_targets,
)
.for_each(|(package_id, _)| {
if let Ok(dep_pkg) = self.get_one(package_id) {
if !dep_pkg.targets().iter().any(|t| t.is_lib()) {
ret.push(dep_pkg);
}
}
});
});
Ok(ret)
}
fn filter_deps<'a>(
pkg_id: PackageId,
resolve: &'a Resolve,
has_dev_units: HasDevUnits,
requested_kinds: &'a [CompileKind],
target_data: &'a RustcTargetData<'_>,
force_all_targets: ForceAllTargets,
) -> impl Iterator<Item = (PackageId, &'a HashSet<Dependency>)> {
resolve.deps(pkg_id).filter(move |&(_id, deps)| {
deps.iter().any(|dep| {
if dep.kind() == DepKind::Development && has_dev_units == HasDevUnits::No {
return false;
}
if force_all_targets == ForceAllTargets::No {
let activated = requested_kinds
.iter()
.chain(Some(&CompileKind::Host))
.any(|kind| target_data.dep_platform_activated(dep, *kind));
if !activated {
return false;
}
}
true
})
})
}
pub fn sources(&self) -> Ref<'_, SourceMap<'cfg>> {
self.sources.borrow()
}

View file

@ -171,20 +171,24 @@ pub fn resolve_ws_with_opts<'cfg>(
feature_opts,
)?;
// Check if there are any dependency packages that do not have any libs.
if let Some(r) = resolve.as_ref() {
for id in member_ids.iter() {
for (package_id, _) in r.deps(*id) {
if let Ok(dep_pkg) = pkg_set.get_one(package_id) {
if !dep_pkg.targets().iter().any(|t| t.is_lib()) {
ws.config().shell().warn(format!(
"No library were found in package `{}`",
dep_pkg.name()
))?
}
}
}
}
let no_lib_warnings: Vec<String> = pkg_set
.no_lib_pkgs(
&resolved_with_overrides,
&member_ids,
has_dev_units,
requested_targets,
target_data,
force_all_targets,
)?
.iter()
.map(|pkg| format!("No lib found in package `{}`.", pkg.name()))
.collect();
if !no_lib_warnings.is_empty() {
ws.config().shell().warn(format!(
"{} The dependent package should have a lib, \
otherwise it is an invalid dependency.",
no_lib_warnings.join("\n")
))?;
}
Ok(WorkspaceResolve {

View file

@ -756,7 +756,69 @@ fn run_with_bin_dep() {
p.cargo("run")
.with_stderr(
"\
[WARNING] No library were found in package `bar`
[WARNING] No lib found in package `bar`. \
The dependent package should have a lib, \
otherwise it is an invalid dependency.
[COMPILING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
[RUNNING] `target/debug/foo[EXE]`",
)
.with_stdout("hello")
.run();
}
#[cargo_test]
fn run_with_bin_deps() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
[dependencies.bar1]
path = "bar1"
[dependencies.bar2]
path = "bar2"
"#,
)
.file("src/main.rs", r#"fn main() { println!("hello"); }"#)
.file(
"bar1/Cargo.toml",
r#"
[package]
name = "bar1"
version = "0.0.1"
authors = []
[[bin]]
name = "bar1"
"#,
)
.file("bar1/src/main.rs", r#"fn main() { println!("bar"); }"#)
.file(
"bar2/Cargo.toml",
r#"
[package]
name = "bar2"
version = "0.0.1"
authors = []
[[bin]]
name = "bar2"
"#,
)
.file("bar2/src/main.rs", r#"fn main() { println!("bar"); }"#)
.build();
p.cargo("run")
.with_stderr(
"\
[WARNING] No lib found in package `bar1`.
No lib found in package `bar2`. \
The dependent package should have a lib, \
otherwise it is an invalid dependency.
[COMPILING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
[RUNNING] `target/debug/foo[EXE]`",