From ca948d62d0a5762c2438da0a0a59034dc0a16cdb Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 1 Jul 2026 14:02:31 -0700 Subject: [PATCH] std.Build: deprecate lazyDependency and dependency in favor of dependencyLazy which has a different function signature and will be eventually renamed to dependency migrating to all dependencies being potentially lazy by setting the flag in build.zig.zon and embracing error.LazyDependencyNeeded propagation as the way to deal with discovered needed dependencies. solves the problem that handling the `null` case from `lazyDependency` was annoying. --- lib/std/Build.zig | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/lib/std/Build.zig b/lib/std/Build.zig index 572a9c519a212ffe2c545563885110cf138a08b8..e0416e836a212b9f726f74a12d050af74056290e 100644 --- a/lib/std/Build.zig +++ b/lib/std/Build.zig @@ -2109,21 +2109,29 @@ fn markNeededLazyDep(b: *Build, pkg_hash: []const u8) void { b.graph.needed_lazy_dependencies.put(b.graph.arena, pkg_hash, {}) catch @panic("OOM"); } +/// Deprecated in favor of `dependencyLazy`. +pub fn lazyDependency(b: *Build, name: []const u8, args: anytype) ?*Dependency { + return dependencyLazy(b, name, args) catch |err| switch (err) { + error.LazyDependencyNeeded => null, + }; +} + /// When this function is called, it means that the current build does, in /// fact, require this dependency. If the dependency is already fetched, it is /// returned. However if the dependency is not yet fetched, then when the build -/// script is finished running, the build will not proceed to the make phase. +/// script is finished running, the toolchain will not proceed to the make phase. /// Instead, the parent process will additionally fetch all the lazy /// dependencies that were actually required by running the build script, -/// rebuild the build script, and then run it again. In other words, if this -/// function returns `null` it means that the only purpose of completing the -/// configure phase is to find out all the other lazy dependencies that are -/// also required. +/// recompile the build script, and then run it again. In other words, if this +/// function returns `error.LazyDependencyNeeded` it means that the only +/// purpose of completing the configure phase is to find out all the other lazy +/// dependencies that are also required. In this case, one must propagate the +/// error all the way up and return it from the main build function. /// -/// It is allowed to use this function for non-lazy dependencies, in which case -/// it will never return `null`. This allows toggling laziness via -/// build.zig.zon without changing build.zig logic. -pub fn lazyDependency(b: *Build, name: []const u8, args: anytype) ?*Dependency { +/// For non-lazy dependencies, this always succeeds. +/// +/// This function will be eventually renamed to `dependency`. +pub fn dependencyLazy(b: *Build, name: []const u8, args: anytype) error{LazyDependencyNeeded}!*Dependency { const build_runner = @import("root"); const deps = build_runner.dependencies; const pkg_hash = findPkgHashOrFatal(b, name); @@ -2134,15 +2142,17 @@ pub fn lazyDependency(b: *Build, name: []const u8, args: anytype) ?*Dependency { const available = !@hasDecl(pkg, "available") or pkg.available; if (!available) { markNeededLazyDep(b, pkg_hash); - return null; + return error.LazyDependencyNeeded; } return dependencyInner(b, name, pkg.build_root, if (@hasDecl(pkg, "build_zig")) pkg.build_zig else null, pkg_hash, pkg.deps, args); } } - unreachable; // Bad @dependencies source + unreachable; // bad @dependencies source } +/// Deprecated in favor of `dependencyLazy`. To get the same behavior as before, use `try` to propagate +/// the potential `error.LazyDependencyNeeded` all the way out of your main build function. pub fn dependency(b: *Build, name: []const u8, args: anytype) *Dependency { const build_runner = @import("root"); const deps = build_runner.dependencies; -- 2.54.0