Add dependencies to targets
This adds a dependencies field to the manifest target schema, listing
other targets on which one depends.
Change-Id: Ib9671761234539a0d10845c9fbeb88db8bbaf0c6
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/qg/+/124954
Reviewed-by: Keir Mierle <keir@google.com>
Commit-Queue: Alexei Frolov <frolv@google.com>
diff --git a/qg/src/project/manifest.rs b/qg/src/project/manifest.rs
index 5e6e003..eef95a4 100644
--- a/qg/src/project/manifest.rs
+++ b/qg/src/project/manifest.rs
@@ -80,8 +80,14 @@
/// A buildable target.
#[derive(Debug, Deserialize, Serialize)]
pub struct Target {
+ /// Provider-specific metadata about how to build the target. If this is
+ /// `None`, the target is virtual, grouping only other target dependencies.
#[serde(flatten)]
pub desc: Option<TargetType>,
+
+ /// List of other targets on which this one depends.
+ #[serde(default)]
+ pub deps: Vec<String>,
}
#[derive(Debug, Deserialize, Serialize)]
diff --git a/qg/src/registry.rs b/qg/src/registry.rs
index dbad628..2ed229f 100644
--- a/qg/src/registry.rs
+++ b/qg/src/registry.rs
@@ -12,7 +12,10 @@
// License for the specific language governing permissions and limitations under
// the License.
-use std::{collections::HashMap, sync::Arc};
+use std::{
+ collections::{HashMap, HashSet},
+ sync::Arc,
+};
use crate::target::{Provider, Target};
@@ -24,6 +27,9 @@
/// All known package providers by name.
providers: HashMap<String, Provider>,
+
+ /// Unknown target dependencies.
+ unresolved_dependencies: HashSet<String>,
}
impl Registry {
@@ -33,6 +39,7 @@
Self {
targets: HashMap::new(),
providers: HashMap::new(),
+ unresolved_dependencies: HashSet::new(),
}
}
@@ -55,18 +62,28 @@
.is_none()
}
- pub(crate) fn add_target(&mut self, package: Target) -> bool {
- let Some(provider) = self.providers.get(package.provider()) else {
+ /// Inserts a target into the registry.
+ pub(crate) fn add_target(&mut self, target: Target) -> bool {
+ let Some(provider) = self.providers.get(target.provider()) else {
return false;
};
let slug = if provider.global {
- package.name().to_string()
+ target.name().to_string()
} else {
- format!("{}:{}", provider.name, package.name())
+ format!("{}:{}", provider.name, target.name())
};
- let target = Arc::new(package);
+ for dep in target
+ .dependencies()
+ .filter(|&d| !self.targets.contains_key(d))
+ {
+ self.unresolved_dependencies.insert(dep.into());
+ }
+
+ self.unresolved_dependencies.remove(&slug);
+
+ let target = Arc::new(target);
self.targets.insert(slug, target);
true
diff --git a/qg/src/target.rs b/qg/src/target.rs
index a72a877..dfb6bc5 100644
--- a/qg/src/target.rs
+++ b/qg/src/target.rs
@@ -41,11 +41,21 @@
}
}
-/// An installable `qg` package.
+/// An buildable `qg` target.
#[derive(Debug)]
pub struct Target {
+ /// The target's name, without a provider namespace.
name: String,
+
+ /// The name of the target's provider.
provider: String,
+
+ /// List of targets on which this one depends, storing their full namespaced
+ /// paths.
+ dependencies: Vec<String>,
+
+ /// Information about how to build the target, specific to a type of
+ /// provider.
metadata: Metadata,
}
@@ -70,6 +80,7 @@
Self {
name: name.to_owned(),
provider: provider.to_owned(),
+ dependencies: target.deps,
metadata: target.desc.map_or(Metadata::DepOnly, Metadata::from),
}
}
@@ -86,6 +97,11 @@
&self.provider
}
+ /// Returns the package's dependencies.
+ pub fn dependencies(&self) -> impl Iterator<Item = &str> {
+ self.dependencies.iter().map(String::as_str)
+ }
+
/// Returns the type of the package as a string.
#[must_use]
pub fn type_string(&self) -> &str {