Run the build script of the "child package" from the parent build script

I could make the root package depend on the child package but, the child package is kind of an example which depends on the root package, so pointing each other in the build.zig.zon, I get error: file exists in multiple modules,
which is kind of expected i suppose?

parent build script for building the examples

fn buildExamples(build_context: BuildContext) !void {
    const b: *std.Build = build_context.b;

    const examples_dep = b.lazyDependency("examples", .{
        .target = build_context.target,
        .optimize = build_context.optimize,
    }) orelse return;

    const exe = examples_dep.artifact("examples");
    const examples_run_cmd = b.addRunArtifact(exe);
    if (b.args) |args| {
        examples_run_cmd.addArgs(args);
    }

    const run_step = b.step("examples", "Builds and runs the examples executable. eg. zig build examples -- <specific example>");
    run_step.dependOn(&examples_run_cmd.step);
}

example build script:

pub fn build(b: *std.Build) !void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});

    const exe = b.addExecutable(.{
        .name = "examples",
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });

    const parent_proj_dep = b.dependency("parent_proj", .{
        .target = target,
        .optimize = optimize,
    });
    exe.root_module.addImport("parent_proj", parent_proj_dep.module("parent_proj"));

    b.installArtifact(exe);
    const run_cmd_step = b.addRunArtifact(exe);
    run_cmd_step.step.dependOn(b.getInstallStep());
    if (b.args) |args| {
        run_cmd_step.addArgs(args);
    }
    const run_step = b.step("run", "Runs it!");
    run_step.dependOn(&run_cmd_step.step);
}

I mean I could try some tricks like discussed here. Or spawn another zig process from the current one…

Just was wondering if there were some nicer way of doing it, may be tihs?std.Build.dependencyFromBuildZig

I don’t think you should create circular dependencies in build.zig.zon.
Instead I think dependencies should form an acyclic graph.

I think you have these options:

  1. put your example within your lib and only have one project (dependency)
  2. put your example outside your lib and create a 3rd project that bundles lib + examples
  3. don’t bundle examples and just link to them as example applications

avoidcyclicdependencies

I think you want to do the first with 2 dependencies (but I don’t think cycles are allowed), but if you want a lib and examples separate but also something that bundles them, I think you need to go to the ABC setup.

A is the library, B is the example and C is the “meta” package that bundles A and B in a way that is nearly identical to the user using A, except that they also are able to run examples from B. Basically merging the options/steps of A and B.

So far I have only done 1. and 3. because they are simpler. I imagine figuring out how to do 2. well would involve some subtle details, but I also imagine that some projects have already done this.

What I have seen more often so far, is that projects just include examples directly and thus end up with a single dependency that does everything, maybe in combination with flags or conditional compilation to avoid downloading gigabytes of data required to get examples to run, until that data is actually needed. I think either mach or zig-gamedev was working like that at some point (but it might have changed since I last looked at it).

This is just my current thinking so far, I would have to get some more practical experience with these situations, before I can say whether this is definitely how it works.

2 Likes

Hmm, I see, the reason I am not going with the first option is it’s kind of just feels like a test component rather than an example(even though it’s showing how to use the exports/functions of the lib), I think examples should be standalone, sort of like also give the user an idea how the packag/lib is being linked or the whole build process too. I think for now spawning another zig process is alright.

1 Like