(sigil build deps)
(sigil build deps) - Dependency Resolution
This library provides dependency graph construction and resolution for building packages in the correct order.
Example usage: (define packages (workspace-load-packages ws ws-dir)) (define graph (build-dependency-graph packages)) (define order (topological-sort graph)) ;; order is a list of package names in build order
Exports
package-build-dependenciesprocedureRuntime build dependencies: explicit runtime dependencies plus implicit Sigil peer dependencies derived from the package's sigil: field. Dev dependencies stay controlled by include-dev-deps?. Optional config-name (a symbol, in rest) applies config-conditional dependency gating: a dep whose configs: list omits config-name is dropped, so e.g. a native-only C dep is excluded from a wasm web config. #f/absent config-name = no filtering. The always-needed implicit Sigil peers (sigil-stdlib/sigil-lib) are never gated.
package-direct-depsprocedureExtract direct runtime dependency names from a package. Returns a list of package name strings. Optional config-name in rest applies config-conditional gating (see package-build-dependencies).
package-dev-depsprocedureExtract ONLY the dev-dependency names from a package, with the same config-conditional gating as the runtime deps. Kept separate from package-all-deps because the two kinds of dependency attach to DIFFERENT build products — see build-product-graph.
package-all-depsprocedureExtract all dependency names from a package (including dev-dependencies) Returns a list of package name strings. Optional config-name in rest gates both runtime and dev deps.
dependency-nameprocedureGet the name from a dependency (handles different dep types)
git-url-to-nameprocedureExtract package name from git URL
build-dependency-graphprocedureBuild a dependency graph from a list of packages Input: alist of (package-name . package) pairs Optional: include-dev-deps? - if #t, includes dev-dependencies Returns: alist of (package-name . (list of dep-names)) Only includes deps that are in packages-alist (filters out external deps that aren't part of this build, like internal workspace deps of redirected packages) Optional args in rest: include-dev-deps? then config-name (a symbol) for config-conditional dependency gating.
test-productprocedureThe graph node for a package's TEST build product.
test-product?procedure#t when NODE is a test product rather than a library.
product-packageprocedureThe package a product node belongs to, for either product kind.
library-productsprocedureKeep only the library products of a sorted product list, in order. This is the package build order: test products are compiled in a later phase and never appear in it.
build-product-graphprocedureBuild the two-product dependency graph.
Every package contributes a LIBRARY node (the package name itself) whose edges are its runtime dependencies. When INCLUDE-DEV-DEPS? is true every package also contributes a TEST node whose edges are its own library plus its dev-dependencies.
Dev edges are not dropped: they are in the graph and topological-sort runs over all of them. Only their ORIGIN vertex changes, from the package to the package's test product, which is where the requirement actually lives.
BE PRECISE ABOUT WHAT THAT DOES AND DOES NOT GUARANTEE. Every edge out of a test product points at a LIBRARY, and nothing anywhere points at a test product — test products are sinks. So a test product can never lie on a cycle, and no dev-dependency configuration can make this sort fail. That is not detection quietly removed; it is the whole reason splitting the vertex is correct rather than merely convenient. A dev dependency is satisfiable whenever the package exists and its library builds, because tests compile in a later phase after every library is done.
The check that survives is therefore the one that can still fail: a cycle among LIBRARIES, i.e. a real runtime dependency cycle. That remains fully detected, including when it is reached only through a dev dependency's own runtime deps. An earlier draft of this comment claimed dev cycles were "still detected and named"; that claim is unfalsifiable by construction and has been removed rather than softened.
As with build-dependency-graph, edges to packages outside PACKAGES-ALIST are dropped: they are external to this build. CONFIG-NAME (a symbol or #f) applies config-conditional gating.
dedupe-external-against-workspaceprocedureDedupe external (from-git / from-path) packages against workspace members.
When a workspace member shares a name with an external dep loaded transitively (typical shape: extracted package's from-git ref to a sibling that is still resident in the consumer's workspace), the merged packages-alist ends up with two entries under the same name. That breaks topological-sort (length comparison fires a spurious "Dependency cycle detected") and causes find-package-path to resolve to the cached external copy instead of the workspace source.
Policy: workspace member always wins. If the fetched copy declares a different version, emit a warning and proceed with the workspace version.
Inputs: workspace-packages: alist of (name . package) for workspace members external-packages: alist of (name . package) for from-git/from-path deps external-paths: alist of (name . path) for the same external deps
Returns: (deduped-external-packages . deduped-external-paths)
warn-on-version-mismatchprocedureEmit a warning when a workspace package and a fetched external copy declare different versions. Silent when either side has no version field or the versions match.
get-build-orderprocedureGet build order for all packages in a workspace Optional: include-dev-deps? - if #t, dev-dependencies are included as requirements of each package's TEST product (see build-product-graph) Returns list of package names in build order (dependencies first)
get-build-order-forprocedureGet build order for a specific package and its dependencies Optional args in rest: include-dev-deps? then config-name (a symbol) for config-conditional dependency gating. Returns list of package names needed to build target (in order)
Reachability and ordering answer two different questions and use two different graphs:
- WHICH packages are needed is asked of the package-level graph with dev edges folded in.
--testscompiles tests for every package in the resulting build order, not just TARGET, so every reached package's dev-dependencies must be in the build set too. That is why this graph, not the product graph, seeds the reachable set. Cycles are harmless here:collect-reachablestops on revisit. - In WHAT ORDER they are built is asked of the product graph, where dev edges hang off test products and so cannot order a library after the test infrastructure built on top of it.
topological-sortvariable(No description)
topological-sort-fromvariable(No description)
detect-cyclesvariable(No description)
has-cycle?variable(No description)