in guppy/src/graph/build.rs [419:513]
fn add(&mut self, target: Target) -> Result<(), Error> {
use std::collections::btree_map::Entry;
// Figure out the id and kind using target.kind and target.crate_types.
let mut target_kinds = target.kind;
let target_name = target.name.into_boxed_str();
let crate_types = SortedSet::new(target.crate_types);
// The "proc-macro" crate type cannot mix with any other types or kinds.
if target_kinds.len() > 1 && Self::is_proc_macro(&target_kinds) {
return Err(Error::PackageGraphConstructError(format!(
"for package {}, proc-macro mixed with other kinds ({:?})",
self.package_id, target_kinds
)));
}
if crate_types.len() > 1 && Self::is_proc_macro(&crate_types) {
return Err(Error::PackageGraphConstructError(format!(
"for package {}, proc-macro mixed with other crate types ({})",
self.package_id, crate_types
)));
}
let (id, kind, lib_name) = if target_kinds.len() > 1 {
// multiple kinds always means a library target.
(
OwnedBuildTargetId::Library,
BuildTargetKindImpl::LibraryOrExample(crate_types),
Some(target_name),
)
} else if let Some(target_kind) = target_kinds.pop() {
let (id, lib_name) = match target_kind.as_str() {
"custom-build" => (OwnedBuildTargetId::BuildScript, Some(target_name)),
"bin" => (OwnedBuildTargetId::Binary(target_name), None),
"example" => (OwnedBuildTargetId::Example(target_name), None),
"test" => (OwnedBuildTargetId::Test(target_name), None),
"bench" => (OwnedBuildTargetId::Benchmark(target_name), None),
_other => {
// Assume that this is a library crate.
(OwnedBuildTargetId::Library, Some(target_name))
}
};
let kind = match &id {
OwnedBuildTargetId::Library => {
if crate_types.as_slice() == ["proc-macro"] {
BuildTargetKindImpl::ProcMacro
} else {
BuildTargetKindImpl::LibraryOrExample(crate_types)
}
}
OwnedBuildTargetId::Example(_) => {
BuildTargetKindImpl::LibraryOrExample(crate_types)
}
_ => {
// The crate_types must be exactly "bin".
if crate_types.as_slice() != ["bin"] {
return Err(Error::PackageGraphConstructError(format!(
"for package {}: build target '{:?}' has invalid crate types '{}'",
self.package_id, id, crate_types,
)));
}
BuildTargetKindImpl::Binary
}
};
(id, kind, lib_name)
} else {
return Err(Error::PackageGraphConstructError(format!(
"for package ID '{}': build target '{}' has no kinds",
self.package_id, target_name
)));
};
match self.targets.entry(id) {
Entry::Occupied(occupied) => {
return Err(Error::PackageGraphConstructError(format!(
"for package ID '{}': duplicate build targets for {:?}",
self.package_id,
occupied.key()
)));
}
Entry::Vacant(vacant) => {
vacant.insert(BuildTargetImpl {
kind,
lib_name,
required_features: target.required_features,
path: target.src_path.into_boxed_path(),
edition: target.edition.into_boxed_str(),
doc_tests: target.doctest,
});
}
}
Ok(())
}