Skip to content

std.Build: add dependencyFromBuildZig#18908

Merged
andrewrk merged 1 commit intoziglang:masterfrom
castholm:dependencyFromBuildZig
Apr 7, 2024
Merged

std.Build: add dependencyFromBuildZig#18908
andrewrk merged 1 commit intoziglang:masterfrom
castholm:dependencyFromBuildZig

Conversation

@castholm
Copy link
Copy Markdown
Contributor

@castholm castholm commented Feb 12, 2024

Given a struct that corresponds to the build.zig of a dependency, b.dependencyFromBuildZig returns that same dependency. In other words, if you have already a @imported a depdency's build.zig, you can use this function to obtain the corresponding Dependency:

// in consumer build.zig
const foo_dep = b.dependencyFromBuildZig(@import("foo"), .{});

This function is also important for packages that expose functions from their build.zig files that need to use their corresponding Dependency (for example, for package-relative paths, or for running system commands and returning the output as lazy paths). This would be accomplished through:

// in dependency build.zig
pub fn getImportantFile(b: *std.Build) std.Build.LazyPath {
    const this_dep = b.dependencyFromBuildZig(@This(), .{});
    return this_dep.path("file.txt");
}

// in consumer build.zig
const file = @import("foo").getImportantFile(b);

Currently, such use cases need to either

1. take a Dependency as argument

// in consumer build.zig
const mach_core = @import("mach_core");
const mach_core_dep = b.dependency("mach_core", .{ ... });
const app = try mach_core.App.init(b, mach_core_dep, .{ ... });

which is prone to user error,

2. call b.dependency with a hard-coded name

// in dependency build.zig
pub fn addWebsite(b: *std.Build, ...) !void {
    const zine_dep = project.dependency("zine", .{ ... });
}

// in consumer build.zig
const zine = @import("zine");
try zine.addWebsite(b, .{ ... });

which only works if the consumer has added that package as a dependency under that exact name (i.e. it must be .zine in the build.zig.zon, not .zine_ssg or some other name the consumer may have chosen), or

3. implement the same logic as dependencyFromBuildZig, which requires the user to know how the undocumented @import("root").dependencies works or that it's even a thing.


There's currently no way to test this in the compiler without setting up a build.zig.zon and some local packages, but I have tested this function with a few packages of my own locally and can report that it works exactly as advertised.

Comment thread lib/std/Build.zig
const pkg = @field(deps.packages, pkg_hash);
if (@hasDecl(pkg, "build_zig") and pkg.build_zig == build_zig) break .{ pkg, pkg_hash };
} else break :find_dep;
const dep_name = for (b.available_deps) |dep| {
Copy link
Copy Markdown
Contributor Author

@castholm castholm Feb 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I should add that there's no need to check for @hasDecl(pkg, "available") because if we get this far, we must have @imported the dependency and know for sure that the package is already fetched even if it's a lazy dependency.

@castholm castholm force-pushed the dependencyFromBuildZig branch from 492f551 to 47c46e2 Compare February 29, 2024 21:33
@Snektron Snektron changed the title std.Build: add dependencyFromBuildZig std.Buwhatild: add dependencyFromBuildZig Mar 1, 2024
@castholm castholm changed the title std.Buwhatild: add dependencyFromBuildZig std.Build: add dependencyFromBuildZig Mar 1, 2024
@castholm castholm force-pushed the dependencyFromBuildZig branch from 47c46e2 to c887963 Compare April 7, 2024 12:43
@castholm
Copy link
Copy Markdown
Contributor Author

castholm commented Apr 7, 2024

Quick repro for testing:

// build.zig
const std = @import("std");
const foo = @import("foo");
pub fn build(b: *std.Build) void {
    b.getInstallStep().dependOn(&b.addInstallFile(foo.importantFile(b), "file.txt").step);
}
// build.zig.zon
.{
    .name = "repro",
    .version = "0.0.0",
    .dependencies = .{
        .foo = .{
            .path = "foo",
        },
    },
    .paths = .{""},
}
// foo/build.zig
const std = @import("std");
pub fn build(b: *std.Build) void {
    _ = b;
}
pub fn importantFile(b: *std.Build) std.Build.LazyPath {
    const this_dep = b.dependencyFromBuildZig(@This(), .{});
    return this_dep.path("file.txt");
}
// foo/file.txt
123

@andrewrk andrewrk force-pushed the dependencyFromBuildZig branch from c887963 to 7f6a972 Compare April 7, 2024 22:54
@andrewrk andrewrk merged commit 05126fc into ziglang:master Apr 7, 2024
@andrewrk andrewrk added zig build system std.Build, the build runner, `zig build` subcommand, package management release notes This PR should be mentioned in the release notes. labels Apr 7, 2024
@castholm castholm deleted the dependencyFromBuildZig branch April 8, 2024 14:37
@andrewrk andrewrk added this to the 0.12.0 milestone Apr 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release notes This PR should be mentioned in the release notes. zig build system std.Build, the build runner, `zig build` subcommand, package management

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants